...making Linux just a little more fun!
By Lew Pitcher
Recently, I changed over to an "always on" ADSL connection from an "on-demand" dialup one, and I now have an opportunity to host a number of internet services from my home server. The one problem I have is that, while my internet is "always on", my ISP occasionally renegotiates the IP address of my ADSL connection, making my internet services difficult to find. Up until now, I've played "hide and seek" with my server, searching for it among a multitude of alternate addresses each time my ISP changes the address.
Now, I could spend a bit of money to lease my own domain name, and subscribe to one of those 'dynamic DNS' services that let you point your domain name at an ever-changing IP address, but I don't need a permanent domain name right now, and I've got other options.
My ISP provides web site hosting for their subscribers, with the usual upload and download volume caps to discourage extensive web hosting. I don't need their host for my content, but it does make a handy 'rendezvous' site to gain access to my system. All I have to do is arrange for my PPPoE client to rewrite my personal web page on my ISP's server every time my ISP gives me a new IP address. If PPPoE can populate that web page with my system's new IP address, I'll always be able to find my system from the outside by looking at my webpage on my ISP's server.
The first thing I needed to do was to arrange for my PPPoE client to be able to pass each new IP address on to something that would update my external webpage.
To do this, I modified my /etc/ppp/ip-up script to execute a new script (/etc/ppp/ip-up.webpage), passing it the PPP 'local' address assigned by my ISP to my end of my PPPoE ADSL connection. The /etc/ppp/ip-up script would then write the webpage and get it to my ISP.
This was a simple change (a literal 'one-liner') in /etc/ppp/ip-up
#!/bin/sh # # ip-up interface-name tty-device speed local-IP remote-IP ipparm # $1 $2 $3 $4 $5 $6 # # (NB: ipparm is string from ipparm parameter in pppd options) # # This file /etc/ppp/ip-up is run by pppd when there's a # successful ppp connection. # # The environment is cleared before executing this script # so the path must be reset. # PATH=/usr/bin:/usr/sbin:/usr/local/bin:/sbin:/bin export PATH # umask 033 echo "$4" >/var/run/$1.ip # # # Build redirect webpage, put it on ISP's webserver /etc/ppp/ip-up.webpage "$4" # /usr/bin/logger -i -t /etc/ppp/ip-up "$1 [$4] connected to ISP [$5]" # Done...
Now that I had arranged for my PPPoE client to run a script, I had to build the script it would run. The script would have to build an HTML document that would redirect the reader to my server's IP address, and FTP that document to my ISP's web server. It would have to preserve the internal security of my system by refraining from exposing my ISP userid and password to local users, and should do this with simple tools and a minimum of programming.
The security aspects were satisfied by making the script 'execute only', so no local user could read it's contents, and by ensuring that no password was exposed to ps(1)[6,7] as a command line argument. The HTML was built through a simple "here document" fed into a cat(1) command that created a temporary file of HTML. The new IP address was written into the HTML through the shell variable substitution process that occurs with "here document" processing. Finally, the temporary file was transmitted to my ISP using a command line ftp(1) command, with its parameters all passed through another "here document". This second "here document" permitted me to pass the user name and password into the FTP client without exposing them on a command line.
The /etc/ppp/ip-up.webpage script (below) is primitive and not very elegant, but it gets the job done.
#!/bin/bash # Validate that we get 1 and only 1 parameter case $# in 1) ;; *) /usr/bin/echo Usage: $0 ip-address-or-dns-name exit 1 ;; esac # the $1 parameter is the IP address assigned to our system # Establish today's date (for html) DATE=`/usr/bin/date` # allocate empty tempfile, terminate if unable to allocate TEMPFILE=`/usr/bin/mktemp /tmp/$1=XXXXXX` || exit 2 # build webpage (redirect) html into tempfile # NB: $1 is our local IP address, passed in from ip-up # $DATE is the current date and time # With the "here document", these variables will # be substituted into the stream by the shell /usr/bin/cat >$TEMPFILE <<END <html> <head> <!-- $DATE --> <meta http-equiv="refresh" content="0;url=http://$1/">; </head> </html> END # send webpage (redirect html) to webserver # ISP_ADDRESS is FTP address of ISP's web server # ISP_USERID is my userid at ISP's FTP server # ISP_PASSWD is my password at ISP's FTP server # NB: ISP_USERID, ISP_PASSWD set as local environment # vars so that they don't appear as parameters # in local 'ps ax' listings # With the "here document", these variables will # be substituted into the stream by the shell ISP_ADDRESS=webserver.isp.com ISP_USERID=username ISP_PASSWD=password /bin/ftp -n <<STOP open $ISP_ADDRESS user $ISP_USERID $ISP_PASSWD ascii put $TEMPFILE index.htm bye STOP # delete tempfile /bin/rm -f $TEMPFILE # terminate exit 0
Now, when my ISP changes my IP address, my PPPoE server invokes /etc/ppp/ip-up, giving it my new IP address. This script invokes my /etc/ppp/ip-up.webpage script, which builds and installs a redirect webpage at my ISP's webserver that points at my new IP address. All I have to do is browse a specific web page on my ISP's webserver, and I'll be redirected to my webpage on my server.
So, with a little scripting, and the resident automation in my Linux system, I've now got a way to find my server from the outside, no matter which IP address my ISP gives it. I guess you could say that my server has given up the game of "hide and seek", and is playing other games now.
Canadian by birth, and living in Brampton, Ontario, I am a career techie
working at a major Canadian bank. For over 25 years, I've programmed on
all sorts of systems, from Z80 CP/M up to OS/390. Primarily, I develop
OS/390 MVS applications for banking services, and have incorporated
Linux into my development environment.