BIND, dynamic DNS
In order to set up dynamic DNS on your server, first you need to make sure you're running BIND9 or better - as of this article, you want BIND 9.3.1.
ph34r# which named /usr/sbin/named ph34r# named - BIND 9.3.1
Okay, good. But we need to dig a little further, because FreeBSD systems have a nasty habit of shipping with elderly BIND8 components higher up in the path than the newer BIND9 versions that go with the actual server. Specifically, we want to check on nsupdate, which we'll be using to do the dynamic updates from client to server:
ph34r# where nsupdate /usr/sbin/nsupdate /usr/bin/nsupdate ph34r# which nsupdate /usr/sbin/nsupdate ph34r# ls -l /usr/bin/nsupdate && ls-l /usr/sbin/nsupdate -r-xr-xr-x 1 root wheel 1252248 May 8 2005 /usr/bin/nsupdate -r-xr-xr-x 1 root wheel 245324 Jul 5 2004 /usr/sbin/nsupdate
AHA! Yup, we've got a crusty old copy of the nsupdate from BIND8 lurking in our PATH higher up than the BIND9 version that goes with our server - and BIND8's nsupdate tool was completely broken and useless. So, we'll get rid of it. (Obviously, if you don't have an older version in the way, you don't need to do this step - but it's important to check first.)
ph34r# cp -p /usr/bin/nsupdate /usr/sbin/nsupdate
With that taken care of, we can start working on the subdomain we want to dynamically update. In this example, we're going to use a parent zone, tehinterweb.net, which is serviced by a FreeBSD box with a static IP address, under our (root) control, and we already have functional DNS for that zone.
First, we need to prepare a "seed" zone file for our subdomain, which is going to be ph34r.tehinterweb.net. This zone file should be very minimal - we only want to put the barest amount of information to flesh out the parts that WON'T ever change. In this case, that will be the SOA record, the NS records, and the MX record (since MX records are based on A records, not on raw IP addresses, the MX won't change even when the dynamic box's IP address does change).
$ORIGIN . $TTL 10 ; 10 seconds ph34r.tehinterweb.net IN SOA r00t.tehinterweb.net. hostmaster.tehinterweb.net. ( 18 ; serial 10800 ; refresh (3 hours) 3600 ; retry (1 hour) 604800 ; expire (1 week) 10 ; minimum (10 seconds) ) $TTL 3600 ; 1 hour NS r00t.tehinterweb.net. NS r00t2.tehinterweb.net. MX 5 cable.ph34r.tehinterweb.net. MX 10 dsl.ph34r.tehinterweb.net. $ORIGIN ph34r.tehinterweb.net.
#!/usr/bin/perl # setddns.pl # # Copyright (c) 05-20-2006, JRS System Solutions # All rights reserved under BSD license: http://www.opensource.org/licenses/bsd-license.php # NOTE: This script requires BIND 9.3.1, and CPAN modules LWP::UserAgent, HTTP::Request, and # HTTP::Response. FreeBSD admins may find the CPAN modules under /usr/ports/www/p5-libwww. # # WARNING: FreeBSD admins must make CERTAIN they are calling the BIND9 version # of nsupdate - FreeBSD systems have a nasty habit of leaving a copy # of the BIND8 version higher up in the PATH, even in systems shipped # with BIND9 in the base install! use LWP::UserAgent; use HTTP::Request; use HTTP::Response; $ROUTERURL = "192.168.0.1/status.html"; $ROUTER_USERNAME = "admin"; $ROUTER_PASSWORD = "password"; $NSUPDATE = "/usr/sbin/nsupdate"; $KEYDIR = "/usr/home/ddns"; $KEYFILE = "Kph34r.tehinterweb.net.+157+23266.private"; $NAMESERVER = "tehinterweb.net."; $HOST = "ph34r.tehinterweb.net"; $TYPE = A; $TTL = 10; $router_url_string = 'http://' . $ROUTER_USERNAME . ':' . $ROUTER_PASSWORD . '@' . $ROUTERURL; $ua = LWP::UserAgent->new; $req = HTTP::Request->new('GET',$router_url_string); $testdata = $ua->request($req)->as_string(); $testdata =~ /(\d{0,3}\.\d{0,3}\.\d{0,3}\.\d{0,3}).*?(\d{0,3}\.\d{0,3}\.\d{0,3}\.\d{0,3})/s; $WAN1 = $2; chdir ("$KEYDIR"); open (NSUPDATE, "| $NSUPDATE -k $KEYFILE"); print NSUPDATE "server $NAMESERVER\n"; print NSUPDATE "update delete $HOST $TYPE\n"; print NSUPDATE "update add $HOST $TTL $TYPE $WAN1\n"; print NSUPDATE "show\n"; print NSUPDATE "send\n"; close (NSUPDATE);