A DDNS Server Using BIND and Nsupdate

If you have your own UNIX machine with a static IP somewhere on the public internet, it's possible to roll your own secure DDNS server using BIND 8 (or greater) and its nsupdate tool on your dynamic UNIX client.
Let's assume that you have a machine on the internet called my.inet.server and a dynamically assigned address on your home machine, my.cable.machine, attached to the net by a cable modem. You own the domain my.home.domain and want to use that name space to statically refer to your cable modem.
On the client side (my.cable.machine), you'll need to:
  • Install BIND 8 or greater
  • Generate a TSIG ID key (needed for security)
  • Set up a script that will notify my.inet.server via nsupdate when your IP changes
On the master nameserver, my.inet.server, you'll need to:
  • Install BIND 8 or greater
  • Create a zone for your home network (or you can add to an existing zone)
  • Create a key entry in /etc/named.conf
  • Add an allow-update entry for your zone in /etc/named.conf
  • Make sure that the timeout in your zone file for your dynamically addressed hosts is very low
To create the TSIG key on my.cable.machine, you can run the following command (as root), substituting whatever name you want for keyname:
dnskeygen -H 128 -h -n keyname
This creates two files, Kkeyname.+157+00000.key and Kkeyname.+157+00000.private. The base64 encoded key included in these files is what you'll later want to put in the key directive in /etc/named.conf on your my.inet.server. I'd suggest putting these two files in with your zone records on my.cable.machine, making sure that they are unreadable/unwritable/unexecutable by normal users.
For our example, we'll say that the files are called /etc/namedb/tsig/Kbob.+157+00000.key, which has the following contents:
bob. IN KEY 513 3 157 hrCDCUNBtlY3sgF8NPnJrg==
And /etc/namedb/tsig/Kbob.+157+00000.private, which contains:
Private-key-format: v1.2
Algorithm: 157 (HMAC)
Key: hrCDCUNBtlY3sgF8NPnJrg==
Use an existing zone entry for your domain, or create a new one. It should look something like the following, though there are other options and keywords that you may want to include:
zone "my.home.domain" {
type master;
allow-transfer {
10.0.0.0; // put your slave servers here
};
file "my.home.domain.zone";
};
Be sure that the domain name is registered with the correct nameserver information and that you populate the initial zone file with the proper records (NS, A, CNAME, MX, whatever is required). If you don't know how to do this, invest some time reading the documentation at ISC's BIND site.
On my.inet.server you need to make the following entry in /etc/named.conf:
key bob {
algorithm HMAC-MD5.SIG-ALG.REG.INT;
secret hrCDCUNBtlY3sgF8NPnJrg==;
};
And then add the allow-update directive to my.home.domain:
zone "my.home.domain" {
type master;
allow-transfer {
10.0.0.0; // replace this with your real slave servers
};
allow-update {
key bob;
};
file "my.home.domain.zone";
};
Be sure to HUP named on my.inet.server after making the changes to /etc/named.conf.
my.inet.server is now ready to accept dynamic updates from my.cable.machine. To send an update, you need to use the nsupdate command on my.cable.machine.
There are lots of DDNS client scripts out there writtin in shell, perl, and even C that will allow you to automatically use nsupdate to change the information on my.inet.server. Do a web or a news search for something that will fit your specific platform and versions of DHCP and DNS.
If you wanted to do an interactive update, instead of an automated one, you'd do:
nsupdate -k /etc/namedb/tsig:bob.
This will bring you to a > prompt. Let's say, for example, that you wanted to add an record for mail.my.home.domain to be the IP of my.cable.machine with a TTL of 10 minutes (600 seconds). You want to keep your timeout low so that changes will propagate rapidly in the event of an IP change. I'll use the loopback address of 127.0.0.1 as an example, but be sure to put the correct address in when you're making your actual changes. You'd do the following:
update add mail.my.home.domain. 600 IN A 127.0.0.1
Then hit return again so that nsupdate executes the command you typed in on the previous line. You can do multiple lines of changes destined for the same zone file before you hit return the second time, but if you want to make changes to two different zone files, you need to make the changes in two blocks.
Once you hit return a second time, a lookup is performed on my.home.domain to extract the nameserver information, and then that nameserver (my.inet.server) is contacted and they key authentication takes place. On my.inet.server, you should now see a log file appear wherever you keep your zone file. The log file will be called my.home.domain.zone.log, and it contains the directives to make the changes you specified with the nsupdate command. Eventually, these changes will be rolled into the actual zone file and the log file will be removed. For the time being, though, these entries are merely in named's cache.
Take a look at the nsupdate man page for more information on the nsupdate syntax and usage for your particular version of BIND.