NSUPDATE HOWTO by Stef Caunter, Feb 2003. Updated Jan 28, 2005. Install nsupdate by installing bind9 on your dhcp client. Run dnssec-keygen as follows to create a key pair for authenticating updates. dnssec-keygen -a HMAC-MD5 -b 128 -n HOST www.foo.ca. Yes, include that dot at the end, to be fully qualified (good habit). Remember, everything depends on that name. It will look like this: Kwww.foo.ca.+157+34827.key I have seen a machine or two be fussy about this being run at the console only. This produces two files with names starting with K, with numbers and "+"s at the end, as above. Put these keys into /var/named with 600 permissions, and sftp them to your ns, putting the keys into its /var/named; confirm 600 permissions (should be fine). You will need an include statement in your name server's named.conf file, which will point at a conf file referencing your key. Call it dnskeys.conf, creating it in /var/named as such: key www.foo.ca. { algorithm hmac-md5; secret "adsfjiott9054kfahG5+Zg=="; }; This file must reference the exact keyname you created with dnssec-keygen. It does not work otherwise. This means everything after the "K" but before the "+157" stuff. Has to be. The secret key is, well, the key in that file. This file must be in /var/named, and be pointed to in named.conf as follows: /* Global options */ include "dnskeys.conf"; options { /* BIND directory */ directory "/var/named"; version " " ; }; zone "foo.ca" in { type master; file "db.foo.ca"; allow-transfer { 50.60.70.80; }; allow-update { key www.foo.ca.; }; }; /var/named is pointed at the dnskeys.conf file, and is specifically told to only allow updates to www.foo.ca. from a host presenting the correct key. Restarting your named should result in no errors to /var/log/messages. Test updating from www.foo.ca. with an update command. /usr/local/bin/nsupdate -k /var/named/Kwww.foo.ca.+157+34827.key -d /etc/nsupdate I use a shell script to refresh my IP on dhcp clients. #!/bin/sh IPADDR=`/sbin/ifconfig ep0|grep 'inet [0-9]'|tr -s " "|cut -d" " -f2` echo "update delete www.foo.ca. A" > /etc/nsupdate echo "update add www.foo.ca. 21600 IN A $IPADDR" >> /etc/nsupdate echo "" >> /etc/nsupdate /usr/local/bin/nsupdate -k /var/named/Kwww.foo.ca.+157+34827.key -d /etc/nsupdate It is critical that /etc/nsupdate has that blank line in it! The script carves out our current IP from ifconfig, populating a variable, which is written into /etc/nsupdate, which in turn is then called as an argument to nsupdate to do the job. Make sure the script runs without error. Check to make sure that the timeout value (21600 in the above example) is sane. If it is too low, meaning lower than your named.conf refresh time, you will get "non-existent zone" errors for your perfectly functional zone if the client's lease is held for a longer time. Unexpected, but possible. See below for how I am running this script in cron to maintain accurate dns. It is also critical that /etc/resolv.conf contains the right information. You must configure /etc/dhclient.conf so that your nameserver and domain are not overwritten by the dhcp server's offer. Mine looks like this: Update as of Jan 23, 2004: A correct supersede line in /etc/dhclient.conf looks like this below. Your list of name servers must be comma separated. You also want the first one listed to be the one receiving the update from the dhcp client. If this sounds obvious, it's not. You may send nsupdate requests as frequently as your cronjob says to lookup only nameservers. With the right nameserver listed first in the supersede statement, you hit the right machine first. interface "ep0" { supersede domain-name "foo.ca"; supersede domain-name-servers 1.2.3.4, 2.3.4.5, 3.4.5.6; request subnet-mask, broadcast-address, time-offset, routers, domain-name-servers, host-name; require subnet-mask; } alias { interface "ep0"; fixed-address 192.168.0.100; option subnet-mask 255.255.255.0; } This means that the dhcp info does not stomp on resolv.conf; nsupdate reads resolv.conf to find out to whom it should send the update. I also configure an internal alias on my nic, so I don't need two nics. This does not work with samba for some reason; it just doesn't. The shell script above needs to be called by dhclient whenever it runs and also in a cron job. Make sure the script contains absolute paths (good habit) to everything. It needs to exist as dhclient_exit_hooks in /etc and be executable (which it probably already is, if you have been following along). Test it with: /etc/rc.d/dhclient restart > dhclient.log 2>&1 and ensure that the update succeeded on dhclient exit. I have found that you need to have fairly frequent updates to keep your records fresh, and I am using a cron call to /etc/dhclient-exit-hooks, running it every 15 minutes. I have several domains doing simultaneous updates. The last four lines of the script is just repeated with the domain name tacked onto the end of the /etc/nsupdate file which is created, so that /etc/nsupdate_foo is created, and used as the input to the actual nsupdate run in dhclient_exit_hooks by cron. Update as of May 25, 2003: I've noticed that dhclient_exit_hooks really does not work on boot with dhclient. The update will only process from running the script from a call from /etc/rc.local after dhcp service has been obtained by dhclient. Don't know why, I'm just calling it as I see it. The steady cron updates are absolutely necessary. I have also found that you can add a new domain which points at another domain which is dynamically updated and that it will sort of work dynamically with no extra effort. I call this a "piggyback update"; it's okay for CNAME virtual web host stuff that doesn't need MX records and shouldn't get a lot of attention. I say "sort of" because any change does not immediately propagate due to the TTL in force, but it will eventually work via the "piggyback" update from the domain which is being dynamically updated. This is quite okay for very unimportant (i.e. freebie) name service that you don't want to have to put in a lot of time generating, installing and scripting a key-based update. Update Feb/Mar 2004: To make any changes to zones to which you are allowing nsupdate you will need to comment out the "allow-update" lines in named.conf before you make the change, remove any .jnl files, increment the serial on the zone and restart named. Key based updating prevents any manual updates from registering with named. Commenting out the updating allows the manual update to happen (confirmed by AXFRs) from slaves; once the manual change has pushed out, you can uncomment the nsupdate allow lines in named.conf for the zone and let nsupdate do its work again. Update Mar 2004: Most of this works fine with BIND nsupdate on Windows2000. You need to set the pretend /etc/resolv.conf located in c:\winnt\system32\drivers\etc\resolv.conf to contain a line for the nameserver receiving updates for the zone. nameserver 50.60.70.80 The syntax is a little different but it works. Update Jan 2005: Here is a tested procedure for updating WinXP to Bind9 unix. The valid syntax for Windows nsupdate is as follows: C:\bind\bin>nsupdate -k c:\Kcsait.ca.+157+nnnnn.key -d c:\update.txt Creating key... The network time has to be synchronized between WinXP and the name server, or the update fails. This is done in "Date and Time Properies/Internet Time" on Control Panel. This script "getip.cmd" pulls ip address and hostname from WindowsXP and creates the update file for nsupdate to use. @echo off :: Get the IP address for /f "tokens=2-6 delims=:. " %%a in ('ipconfig') do if "%%a"=="Address" (if not "%%b"=="0" call :test %%b %%c %%d %%e) goto :EOF :test if %1==10 goto nsupdate goto :EOF :nsupdate echo update delete %USERDOMAIN%.csait.ca. A > c:\update.txt echo update add %USERDOMAIN%.csait.ca. 86400 IN A %1.%2.%3.%4 >> c:\update.txt c:\bind\bin\nsupdate -k c:\Kcsait.ca.+157+56788.key -d c:\update.txt :EOF As long as the path to your nsupdate.exe is valid, your update will send to the name server listed in your c:\windows\system32\drivers\etc\resolv.conf.