Search

Dynamic DNS Services Update Scripts

0 views

Strangely enough, I never had any need for a dynamic DNS service until this week. In retrospect, it really does seem odd that I've never needed such a service before now, but so be it. My problem this week was that I wanted to set up a http://www.dyndns.org, sign up for a free account, and it's done. I assigned my current cable dynamic ip address to the hostname I chose, and now "xyz.dyndns.info" points to my cable modem. In my case, I could have stopped there. The only time the dynamic ip changes is when I change routers. While that is something I do fairly frequently in the course of testing things, I certainly didn't need to do it during the run of this demo, and even if I did, I could pop back to dyndns.org and update myself. But what if I needed this for a longer term or if my dynamic ip address were more dynamic than it is now? Well, there are hundreds and hundreds of clients that will update dynamic dns services. Many home-use routers even have a client built into them (though the services warn against using these because most update too often for no reason). Well, as usual, I don't want to use someone else's code. I'd rather understand how the thing works and do it myself. I might use someone else's code after that, but almost always I want to get my own hands dirty first. So, first problem: how to find the current ip address? If you are behind a firewall, there may be some way to get the device or computer to tell you. It might be as simple as an "ifconfig eth1" if you are using a Linux router. But I change firewalls frequently, so I can't depend on that. There are places on the net that can help. For example, you can use lynx --dump http://yourserver.com/whatsmyip.html?564312 > /dev/null The "whatsmyip.html" doesn't exist, and the extra "?563412" is just a number you make up. These accesses will be logged, so on the server we'll find these in our access_log: 66.31.38.153 - - [18/Sep/2004:10:01:01 +0000] "GET /whatsmyip.html?564312 HTTP/1 .0" 404 2240 "-" "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" 66.31.38.153 - - [18/Sep/2004:11:01:01 +0000] "GET /whatsmyip.html?564312 HTTP/1 .0" 404 2240 "-" "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" 66.31.38.153 - - [18/Sep/2004:12:01:01 +0000] "GET /whatsmyip.html?564312 HTTP/1 .0" 404 2240 "-" "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" 66.31.38.153 - - [18/Sep/2004:13:01:16 +0000] "GET /whatsmyip.html?564312 HTTP/1 .0" 404 2240 "-" "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" 66.31.38.153 - - [18/Sep/2004:14:01:01 +0000] "GET /whatsmyip.html?564312 HTTP/1 .0" 404 2240 "-" "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" A simple shell script can extract "66.31.38.153" which is what we need to know. That script could continue on to update the dynamic dns service. So how do you update the service? Every service has their own method, but we'll just look at dyndns.org. You can find the full details at #!/usr/bin/perl use LWP::UserAgent; use HTTP::Request; use HTTP::Response; $debug=0; $checkip=1; chdir("/root/dyndns") or die "can't chdir /root/dyndns $!"; # Try to get a lock just in case we got called again # this isn't 100% foolproof but is good enough for this purpose open("O",">lock"); flock(O, 2) ; #block here if (-e "badstatus") { &nbsp logit("badstatus "); &nbsp myexit(0); } # Don't check more often than every ten minutes. # We call this with cron, but this just makes sure open(F,"currenttime"); $last=<F>; chomp $last; close F; $last+=600; $now=time(); if ($checkip) { &nbsp while ($last > $now) { &nbsp&nbsp printf "sleeping %0.2d ",($last - $now); &nbsp&nbsp sleep ($last - $now); &nbsp&nbsp $now=time(); &nbsp } &nbsp open(F,">currenttime"); &nbsp print F $now; &nbsp close F; &nbsp $what="http://checkip.dyndns.org/"; &nbsp $ua=LWP::UserAgent->new(); &nbsp $ua->agent("APL Perl/1.0"); &nbsp $req=HTTP::Request->new(GET=>$what); &nbsp $response=$ua->request($req); &nbsp if ($response->is_error() ) { &nbsp&nbsp logit("Couldn't get $what"); &nbsp&nbsp myexit(0); &nbsp } else { &nbsp&nbsp $currentip=$response->content(); &nbsp&nbsp $currentip=~ s/.*Current IP Address: *//; &nbsp&nbsp $currentip=~ s/..body.*//; &nbsp&nbsp chomp $currentip; &nbsp&nbsp open(F,"currentip"); &nbsp&nbsp $lastip=<F>;close F; &nbsp&nbsp chomp $lastip; &nbsp&nbsp open(F,">currentip"); &nbsp&nbsp print F "$currentip "; &nbsp&nbsp close F; &nbsp } } open(F,"lastupdate"); $lastup=<F>;close F; chomp $lastup; $days=($now - $lastup)/(3600 * 24); if ($days >= 28 or $lastip != $currentip or $debug) { &nbsp&nbsp logit("update $days $lastip $currentip "); &nbsp &nbsp $what="http://members.dyndns.org/nic/update?system=dyndns&hostname=test.dynd ns.org&myip=$currentip"; &nbsp&nbsp $ua=LWP::UserAgent->new(); &nbsp&nbsp $ua->agent("APL Perl/1.0"); &nbsp&nbsp $req=HTTP::Request->new(GET=>$what); &nbsp&nbsp $req->authorization_basic('test', 'test'); &nbsp&nbsp $response=$ua->request($req); # Lynx equivalent is # # lynx --dump -auth youraccount:yourpass "http://members.dyndns.org/nic/update?system=dyndns&hostname=yourhost.dyndns.info&myip=$currentip" # &nbsp&nbsp if ($response->is_error() ) { &nbsp&nbsp&nbsp print "Error "; &nbsp&nbsp&nbsp myexit(0); &nbsp&nbsp } else { &nbsp&nbsp&nbsp $status=$response->content(); &nbsp&nbsp&nbsp print "$status "; &nbsp&nbsp&nbsp open(F,">lastupdate"); &nbsp&nbsp&nbsp print F $now;close F; &nbsp&nbsp&nbsp myexit(0) if ($status =~ /good/ or $status =~ /nochg/); &nbsp&nbsp&nbsp logit("Dyndns says $status "); &nbsp&nbsp&nbsp myexit(0); &nbsp&nbsp } } sub myexit { &nbsp&nbsp $a=shift; &nbsp&nbsp flock(O, 8); &nbsp&nbsp close O; &nbsp&nbsp exit $a; } sub logit { &nbsp&nbsp $a=shift; &nbsp&nbsp print $a; } *Originally published at

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!