Publications

Configuring Dynamic DNS & DHCP on Debian

This short article was prompted by my question on the Debian-Administration forum site, where I was able to get some answers to the issues I faced and I did promise to post a solution if I got one.

For the average home computer user there is no need to install a complex package such as the Internet Software Consortium's BIND DNS or DHCP server, since there are far simpler lower resource tools to use, for example dnsmasq. For those who you wish to learn how to use ISC's BIND and DHCP, for example as a learning exercise, this is how I got it all to work in Debian Sarge, the current stable version of Debian GNU/Linux.

Caveat

The example configuration shown below is perfectly suitable for a small isolated network, separated from the public Internet. Do not use this configuration directly on an exposed network, additional "hardening" is required. The recent DNS cache poisoning issue has demonstrated the importance of correct DNS configuration.

The explanation given here is suitable for Debian 3.1 "Sarge", 4.0 "Etch" and 5.0 "Lenny". It does not include a number of extra features that became available after Sarge. It should not be assumed that it is best practice.

Installation of Packages

The version of ISC BIND DNS and DHCP servers installed by default in Debian stable are the older versions, which will not actually work together. If you have either server installed you need to remove it and upgrade to the newer version of each package. The newer versions are available in the Debian stable archive so you do not need a back-port from testing.

[user@box ~]$ sudo aptitude remove bind dhcp
[user@box ~]$ sudo aptitude install bind9 dhcp3-server

Let aptitude or apt-get figure out and resolve any dependencies. You will get a set of basic configuration files and start scripts all created for you in the usual Debian way.

To set-up DNS you need to set your domain rules as per normal BIND9 format. BIND9 does have a reputation for being complex but you can find help in the man pages which are complete, if very long, and there are good books to help you get through (see below). Setting up the DHCP server is by comparison much simpler; set that up as you need.

The hard bit is getting the two to talk to each other, as this is less well documented and the documentation that does exist does contradict itself. It was my difficulties with getting the DHCP server to automatically update the DNS server that lead me ask a question on the D-A.org web site. Though I got no perfect answer, I was able to piece together enough to generate this working solution.

Configuring BIND9

/etc/bind/named.conf

You need to tell BIND that it is okay to allow other applications to update it. I added the following to my BIND9 configuration, everything else was left as stock Debian. My DHCP server and DNS server are on the box, so here I am only allowing localhost to perform the update. The file rndc-key is a file containing a shared secret, so that BIND9 knows that it is an approved application sending instructions.

controls {
        inet 127.0.0.1 allow {localhost; } keys { "rndc-key"; };
};

/etc/bind/named.conf.local

Here is my local zone details, suitably modified. Here I let BIND know which domains it can update; in my case I only have one domain to deal with. I am also loading in the shared secret key in at this stage. You can see I am using a private IP address range.

// Add local zone definitions here.
zone "network.athome" {
        type master;
        file "/etc/bind/db.network";
        allow-update { key "rndc-key"; };
        notify yes;
};

zone "0.168.192.in-addr.arpa" {
        type master;
        file "/etc/bind/db.192.168.0";
        allow-update { key "rndc-key"; };
        notify yes;
};

include "/etc/bind/rndc.key";

/etc/bind/rndc.key

The secret key is created with the rndc-confgen tool. If your DHCP and DNS servers are on separate machines you need to copy the file between them or arrange for one machine to remotely access the file system of the other. The key file should be owned by root and inaccessible by all other users. After you have created the key ensure that you delete any temporary files created when you created the key (rm K.*).

key "rndc-key" {
        algorithm       hmac-md5;
        secret          "lgkbhjhtthgtlghtl6567==";
};

db files

Set up your zone databases as normal. You do not need to do anything fancy.

Configuring DHCP3 Server

By default the ISC DHCP3 server shipped in Debian Sarge does not do dynamic DNS update. You simply need to enable it. Below are the options I selected for my system.

/etc/dhcp3/dhcpd.conf

You have to turn on the updating with the ddns-update-style interim command. I have client-updates ignore as Windows machines try to set their FQDN, not just their hostname, which causes problems. I have included the key so the two server daemons can trust each other.

# Basic stuff to name the server and switch on updating
server-identifier       server;
ddns-updates                on;
ddns-update-style           interim;
ddns-domainname             "network.athome.";
ddns-rev-domainname         "in-addr.arpa.";
ignore                      client-updates;

# This is the key so that DHCP can authenticate it's self to BIND9
include                     "/etc/bind/rndc.key";

# This is the communication zone
zone network.athome. {
    primary 127.0.0.1;
    key rndc-key;
}

# Normal DHCP stuff
option domain-name              "network.athome.";
option domain-name-servers      192.168.0.60, 192.168.0.1;
option ntp-servers              192.168.0.60;
option ip-forwarding            off;

default-lease-time              600;
max-lease-time                  7200;
authoritative;

log-facility local7;

subnet 192.168.0.0 netmask 255.255.255.0 {
    range           192.168.0.100 192.168.0.200;
    option broadcast-address    192.168.0.255;
    option routers              192.168.0.1;
    allow                       unknown-clients;

    zone    0.168.192.in-addr.arpa. {
            primary 192.168.0.60;
            key             "rndc-key";
    }

    zone    localdomain. {
            primary 192.168.0.60;
            key             "rndc-key";
    }
}