Dynamic DNS with DHCP and BIND9

There is a feature in ISC's DHCP and BIND software which is generally not used and not much documentation exists for it. DHCP has the ability to update DNS zones on a BIND name server automatically as it assigns an IP address to a DHCP client. This can either be the hostname the client sends the server as part of it's request for an address in the case of dynamic ranges, or it can be a set hostname in the case of static addresses.

Getting this to work is a bit of a black art. Various searches on google for config examples show several however none of them ever seemed to work for me. I now know and understand why. It was because I do more than the average user does and my extra bits broke it. So I have written this tutorial to help others who may wish to do what I have done.

This is written with FreeBSD in mind. If you use another operating system then the dhcpd.conf and named.conf are going to be identical but the startup scripts etc will be different. As I only use FreeBSD I can not help with this but I'm sure it is probably easy enough to work out.

This apparently is supported under BIND8 however if you are going to all this hassle you may as well use BIND9. My example named.conf is for BIND9 but for BIND8 all you should have to do is remove the controls declaration for rndc.

To begin with install ISC-DHCP and BIND9 from the ports tree:

  1. cd /usr/ports/net/isc-dhcp3 && make install clean
  2. cd /usr/ports/net/bind9 && make install clean

Note that if you wish to replace BIND8 from the base system then you can add PORT_REPLACES_BASE_BIND9=yes and NO_BIND=yes to /etc/make.conf. I personally prefer keeping installed software seperate from the base system but it is up to you. If you keep the old base BIND8 then you can set your system to start the new BIND9 by putting named_program="/usr/local/sbin/named" in /etc/rc.conf, you may also wish to set named_flags="-c /path/to/named.conf" if you place this file somewhere other than where it is expected which is /usr/local/etc/named.conf.

Once they are both installed we need to configure them. We will start with DHCP. Edit /usr/local/etc/rc.isc-dhcpd.conf and edit dhcpd_ifaces= to suit your setup. I am using my system as a router and so I have two interfaces. One out to the internet and one on my internal LAN. I only wish to have the DHCP service on the LAN and so I put the interface name of my LAN card in here. You also need to rename /usr/local/etc/rc.d/isc-dhcpd.sample.sh to isc-dhcpd.sh so that it starts on boot.

Next we need to write a dhcp.conf file. This will not exist yet but needs to be created in /usr/local/etc. A stripped down version of mine looks like this:

server-identifier tao.xtaz.co.uk;
authoritative;

ddns-update-style interim;
update-static-leases true;

key md5hash {
	algorithm hmac-md5;
	secret "secret-md5-key";
}

zone xtaz.co.uk. {
	primary 127.0.0.1;
	key md5hash;
}

zone 1.168.192.in-addr.arpa. {
	primary 127.0.0.1;
	key md5hash;
}

subnet 192.168.1.0 netmask 255.255.255.0 {
	range 192.168.1.100 192.168.1.200;
	option subnet-mask 255.255.255.0;
	option broadcast-address 192.168.0.255;
	option domain-name "xtaz.co.uk";
	one-lease-per-client on;
	default-lease-time 43200;
	max-lease-time 86400;
	option routers 192.168.1.1;
	option domain-name-servers 192.168.1.1;
	option smtp-server 192.168.1.1;
	option ntp-servers 192.168.1.1;
}

host shakira {
	hardware ethernet 00:04:76:8d:c5:fd;
	fixed-address 192.168.1.10;
	ddns-hostname "shakira";
}

host zen {
	hardware ethernet 00:50:fc:9b:9b:e8;
	fixed-address 192.168.1.11;
	ddns-hostname "zen";
}

I am not going to go into detail with explaining every part of this file but basically the parts you need to change are the zone's you want the DHCP daemon to update for you, the range of addresses you wish to give non-static clients, the static addresses for your clients, and the IP addresses of your subnet configuration such as router address etc. The "secret-md5-hash" is generated when you configure BIND9 in a minute.

So on to BIND9! I am not going to go into setting up BIND from scratch. I assume you already have a working nameserver when you read this. I am only going to mention the BIND9 and DHCP relevent parts. There is plenty of documentation on creating zone files etc if you do not know how to do this.

First we need to create a key and our rndc.conf file. The easiest way to do this is to go into /usr/local/etc and type rndc-confgen -a. This will create your rndc.conf. Edit this file and change the default-key and key parameters from "key" to "md5hash" if you want it to match my example dhcpd.conf and named.conf files. Then take the long md5 hash and paste that into the dhcpd.conf you previously created in place of the "secret-md5-hash".

Now all we need to do is create our named.conf for BIND9:

options {
        directory "/usr/local/etc/named";
	listen-on {
			192.168.1.1;
			127.0.0.1;
		};
};

key "md5hash" {
	algorithm hmac-md5;
	secret "secret-md5-hash";
};

controls {
	inet 127.0.0.1 port 953
	allow { 127.0.0.1; } keys { "md5hash"; };
};

zone "." {
        type hint;
        file "db.root";
};

zone "0.0.127.in-addr.arpa" {
        type master;
        file "db.rev.localhost";
};

zone "1.168.192.in-addr.arpa" {
        type master;
        file "db.rev.lan";
	allow-update { key "md5hash"; };
};

zone "xtaz.co.uk" {
        type master;
        file "db.xtaz.co.uk";
	allow-update { key "md5hash"; };
        };

Again I am not going to go into detail with this file but all you need to do is add the controls directive with your previously generated md5 hash and then add the allow-update directives to each of your zones you previously configured in the dhcpd.conf.

And that is all there is to it. If you start bind9 and dhcpd up you should find that your LAN clients should be able to get their addresses from DHCP now and that the DNS zone is automatically updated with their hostname.