Using Perl to Defeat Provider Restrictions

by TRM

In this article I will describe how two Perl scripts can work together to update your hosted website with links to your personal home web server.  This is handy if you have a broadband ISP that changes your IP address on a regular basis, or if you just need to be able to handle the rare occasion where that might happen.

Background

A few years ago, the company I work for was selling some of their old PCs to the employees.  I purchased one of these systems because I wanted the 17" monitor.  The computer was a no-name 200 MHz with 32 MB of RAM.  Not knowing what else to do with this box, I installed Linux.

It soon became a headless Apache/MySQL server.  Having experience with Perl and databases, I began writing a small application that would allow me to save and catalog work-related information (like Oracle optimization tricks, which I have trouble remembering on my own ).

I have broadband service and a home network.  A diskless Coyote Linux router provides NATing, DHCP, and firewalling.  I opened a hole in the firewall and port forwarded to my new Linux box.  Now I could access my web server from work and home!

The Problem

Occasionally, my ISP updates my IP address.  Or the power goes out for a day and my old IP gets reallocated.  Whatever the reason, every now and then my IP address changes.  The more I came to depend on my little web application (which was growing all the time), the more inconvenient these IP changes became.  I was the only one who was going to access the server so I didn't see the point of subscribing to a DNS service.

I tried to find a way to email myself at work whenever the IP changed, but every attempt I made to determine my external (ISP provided) IP address from the Linux server using a script ended in failure because of the NATing.  I could have loaded a script onto the boot floppy of the Coyote router, but there isn't much room on that floppy for extra scripts, so running a program from there didn't seem like a good option.

The Solution

Then I remembered that when a web server receives a request the IP address of the requester is available to CGI scripts.  So I wrote two Perl scripts.  The first script is run from a cron job on my Linux server at home.  It makes a web site request.  The second script runs on my free website account.  It handles the request from the first script and creates files which are later included in one of the pages on the site using Server-Side Includes (SSI).

Here is the first script:

#!/usr/bin/perl
#########################
## setIP.pl - requests a page from a website and just exits.
#########################

use strict 'refs';
use LWP::Simple;

my ($content);
my $linkURL = "http://<your external site here>/cgi-bin/getIP.pl";

$content = get ($linkURL);

This script doesn't do much, but it does introduce the LWP Perl module.  LWP provides an easy way to implement web clients in Perl.  In this case, all we want to do is send a request to our Perl script on the external site.  We don't care about getting a page back so the script terminates right after the request.

I created a cron job that executes this script once every hour.  So if the IP address of my home web server changes, the links on my external site will have the new IP within the hour.  This is really handy if the IP changes while I'm trying to use my application from work.  Of course, I could run this script every five minutes if I wanted to.

The second script does most of the work (not that there's much to do).  It uses the web server's REMOTE_ADDR environment variable to create small files on the web server.  Using SSI these files are later included into a page on my external site.

#!/usr/bin/perl
#########################
## getIP.pl - Save the IP address of the requester
#########################

use strict 'refs';

$remoteAddress = $ENV{REMOTE_ADDR};

#
# This saves a file on the server that contains just the IP address,
#  just for shits and giggles.
#
open ( OUTFILE, ">homeIP.txt" );
print OUTFILE $remoteAddress;
close OUTFILE;

#
# This file contains an HTML anchor that points to the application
# on my home server.
#
open ( OUTFILE, ">appname.html" );
print OUTFILE "<A HREF=\"http://$remoteAddress/appname\">My Application</A>";
close OUTFILE;

#
# This file has an HTML anchor that points to the same application
# on my home server.  But this time over SSL (port 443)
#
open ( OUTFILE, ">secure_app.html" );
print OUTFILE "<A HREF=\"https://$remoteAddress/appname\">My App(secure)</A>";
close OUTFILE;

#
# This file has an HTML anchor that points to a second application that I use.
#
open ( OUTFILE, ">secondApp.html" );
print OUTFILE "<A HREF=\"http://$remoteAddress/secondApp\">Second App</A>";
close OUTFILE;

#
#  A static web page on the home server
#
open ( OUTFILE, ">page.html" );
print OUTFILE "<A HREF=\"http://$remoteAddress/page.html\">Static Page</A>";
close OUTFILE;

Now that I have four new files on the hosted web site, what do I do with them?  I created a SHTML file that takes those files and places them inside a web page.  Now the page can be viewed and the links are always up to date.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Links to home server</title>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tr><td>
<p align="center"><font size="6"><strong>My Stuff at Home</strong></font>
<BR>
<!--#include file="cgi-bin/appname.html" -->
<BR>
<!--#include file="cgi-bin/secure_app.html" -->
<BR>
<!--#include file="cgi-bin/secondApp.html" -->
<BR>
<!--#include file="cgi-bin/page.html" -->
<BR>
</td></tr>
</table>
</body>
</html>

This may not be the most elegant solution to the problem.  In fact, it's a bit of a kludge.  But it doesn't rely on an external DNS provider and was easy to implement.

Related Links

free.prohosting.com - reliable free web hosting with CGI support.

lwp.linpro.no/lwp/ - for information about the LWP and libwww-perl Perl modules.

Code: setIP.pl

Code: getIP.pl

Thanks to: Joshua Jackson for creating Coyote Linux, Larry Wall for Perl - the most fun programming language on the planet, Jen, Will, and Maddy for putting up with my computer habit.

Return to $2600 Index