DDNS (Dynamic DNS updates) for DHCP hosts

When a new client joins a DHCP network, the ISC DHCP server can automatically contact a ISC BIND (8/9) and add the client's hostname to the DNS zone.

Peter Poeml from SUSE wrote a small HOWTO and a DDNS key frontend shell script, however its availability on the Internet is about zero, so I post it here.


The ISC DHCP server v3 supports dynamical DNS updates (DDNS), as do BIND8/9. There are several standards in the works; for now the best way to do it seems to be updates done by the DHCP server only (not by the clients themselves).

Short outline of how things work together:

The following instructions should get you started.
They are basically taken from the dnskeygen and dhcpd.conf man pages.

(DDNS-HOWTO) Make a key to be used by dhcpd to authenticate for DNS updates.

You can use the script /usr/bin/genDDNSkey which essentially runs BIND's key generating utility, extracts the secret from the K*.private key file and puts it into the file /etc/named.keys. File name and key name can be specified on the commandline, or via shell environment. Install the bind-utils package if you do not have the script, or get it below. Call genDDNSkey --help for usage info.

The simplest example to use it is:


which is equivalent to

genDDNSkey --key-file /etc/named.key --key-name DHCP_UPDATER

thereby using the defaults that fit the rest of this readme.

The script works both for BIND8 and BIND9.

(DDNS-HOWTO) ;Configure dhcpd

/etc/dhcpd.conf needs these additional lines:

ddns-update-style interim;
ignore client-updates;

include "/etc/named.keys";

and in the subnet declaration:

subnet netmask {
    range dynamic-bootp;

    zone whirl. { primary; key DHCP_UPDATER; }
    zone 0.168.192.in-addr.arpa. { primary; key DHCP_UPDATER; }

Note that this setup implies that the DNS server runs on the same machine (, but you can easily change that.

Since the DHCP server runs in a chroot jail by default, the key file needs to be copied into the jail because dhcpd cannot see files outside it. This can easily be achieved by adding /etc/named.keys to the value of DHCPD_CONF_INCLUDE_FILES in /etc/sysconfig/dhcpd (SUSE), which can be done via YaST, or via any editor.

(DDNS-HOWTO) Configure named

Append something along these lines to /etc/named.conf:

include "/etc/named.keys";

zone "whirl" in {
    type master;
    file "dyn/whirl.zone";
    allow-update { key DHCP_UPDATER; };
zone "0.168.192.in-addr.arpa" in {
    type master;
    file "dyn/0.168.192.zone";
    allow-update { key DHCP_UPDATER; };

Since named runs, by default, in a chroot directory since SUSE 8.2, we need to add /etc/named.keys to the value of NAMED_CONF_INCLUDE_FILES in /etc/sysconfig/named, just as we did it with dhcpd.

Since named runs, by default, as user "named" since SUSE Linux 8.2, there is another issue to be sorted out: named needs to create its .jnl files somewhere, but it is not allowed to do that in its working directory (/var/lib/named) for security reasons. See /usr/share/doc/packages/bind9/README.SuSE (or just .../packages/bind/..., without 9) for a solution. (See below for the file "NAMED File Permissions".)

If you got this far, there is a reasonable chance that you have got DDNS working. Obviously, you need some zone files :) One further note: if you provide dummy hostnames like d1, d2, d3, ... for the dynamical clients they will have a hostname even if they do not send a hostname (and no DDNS update is done).

If it does not work, closely watch /var/log/messages. In almost all cases the messages give the right clues.

File Permissions

(Replica of /usr/share/doc/packages/bind/README.SuSE for those who do not own a SUSE Linux.)

The BIND daemon process named runs by default in a chroot jail, /var/lib/named/ and as user named. You could disable the chroot behaviour by setting NAMED_RUN_CHROOTED with the YaST sysconfig or any editor in /etc/sysconfig/named to "no".

The BIND package uses by default /var/lib/named/ to store its zone files.

For security reasons named runs as user named and the name server directory is owned by user and group root. Therefore slave zone files can only be stored at /var/lib/named/slave/, because this directory is owned by user named.

The same applies to dynamically updated zones. Here the zone and the journal files must be owned by named to allow the named process to write these files. From time to time as an intermediate step named dumps the current content of the journal to a new created temporary file.

If you use dynamic updated zones, you must change the file definition of the concerned zone to use the subdirectory /var/lib/named/dyn/ like in the following example.

zone "example.net" in {
    type master;
    file "dyn/example.net.zone";
    #[ other unlisted options ]

The owner of /etc/named.conf is set to root:named and to permissions 0640 by default. By this only root can change the file, user named and the named process can read, but others cannot access the file. This is indispensable if the configuration file contains shared secrets for zone updates. Ensure that all named configuration files are readable either by the user or group named.

genDDNSkey.sh script

Grab genDDNSkey.sh

Personal configuration

As you have seen, the genDDNSkey.sh script packs all newly generated keys into /etc/named.keys. However, I like to keep each key in a separate file (there is more than just a DHCP_UPDATER key), so I have e.g. /etc/ddns.key (with the DHCP_UPDATER thing, which I also call DDNS_KEY rather than DHCP_UPDATER), /etc/omapi.key for the DHCP OMAPI interface, and of course /etc/rndc.key for the NAMED remote interface.

That is also because certain keys are only thought for DHCP (omapi.key), some only for NAMED (rndc.key), and some for both (ddns.key), so it is indeed wise to separate the keys into single files.