Dynamic DNS updates for DHCP on Ubuntu 12.04

Configuring your nameserver for dynamic updates for DHCP hosts is a common task, but the online documentation is a bit outdated and incorrect in many ways. Let’s fix it.

A basic DNS configuration will look like this:

/etc/bind/named.conf

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.dhcpupdate";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

We added the include named.conf.dhcpupdate to the default file. Let’s see the rest.

/etc/bind/named.conf.options

options {
        directory "/var/cache/bind";

        forwarders {
                8.8.8.8;
                8.8.6.6;
        };

        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };
};

We used Google DNS servers as forwarders (it’s a good default).

/etc/bind/named.conf.dhcpupdate

key dhcpupdate {
  algorithm hmac-md5;
  secret "waZulpdc0rzMahbulbd34C==";
};

We created the key using:

$ su -
passwd:
# cd /etc/bind/
# dnssec-keygen -a hmac-md5 -b 128 -n USER dhcpupdate
[...]
# cat Kdhcpupdate.+157+31337.key
dhcpupdate. IN KEY 0 3 157 waZulpdc0rzMahbulbd34C==

You should create your own key, otherwise everyone reading this post will be able to tamper with your DNS :)

/etc/bind/named.conf.local

zone "stardata.lan" {
        type master;
        file "/var/cache/bind/db.stardata.lan";
        allow-update { key dhcpupdate; };
};

zone "0.168.192.in-addr.arpa" {
        type master;
        notify no;
        file "/var/cache/bind/db.192";
        allow-update { key dhcpupdate; };
};

It’s very important that your zone files are in /var/cache/bind/, otherwise AppArmor will deny the write permissions to named and the daemon will not update the zones.

/etc/bind/named.conf.default-zones

We kept the default for this file and related files (db.root, db.local, db.127, db.0, db.255)

/var/cache/bind/db.stardata.lan

$ORIGIN .
$TTL 7200 ; 2 hours
stardata.lan            IN SOA  gw.stardata.lan. hostmaster.stardata.lan. (
                                2012070901 ; serial
                                3600       ; refresh (1 hour)
                                1800       ; retry (30 minutes)
                                604800     ; expire (1 week)
                                7200       ; minimum (2 hours)
                                )
                        NS      gw.stardata.lan.
$ORIGIN stardata.lan.
$TTL 3600 ; 1 hour
dns                     A       192.168.0.2
gateway                 A       192.168.0.2
gw                      A       192.168.0.2
ns                      A       192.168.0.2

This is a very simple and basic configuration, covering only our DNS server (192.168.0.2).

/var/cache/bind/db.192

$ORIGIN .
$TTL 604800     ; 1 week
168.192.in-addr.arpa    IN SOA  gw.stardata.lan. hostmaster.gw.stardata.lan. (
                                2012050804 ; serial
                                604800     ; refresh (1 week)
                                86400      ; retry (1 day)
                                2419200    ; expire (4 weeks)
                                604800     ; minimum (1 week)
                                )
                        NS      gw.
$ORIGIN 0.168.192.in-addr.arpa.
2                       PTR     gw.stardata.lan.

And this is the reverse zone.

Now, you’ll want to test this configuration. Restart bind (service bind9 restart), then create a PTR and an A record:

$ nsupdate
> server localhost
> key dhcpupdate waZulpdc0rzMahbulbd34C==
> zone 0.168.192.in-addr.arpa
> update add 50.0.168.192.in-addr.arpa 600 IN PTR provaprova.stardata.lan.
> send
> server localhost
> key dhcpupdate waZulpdc0rzMahbulbd34C==
> zone stardata.lan
> update add provaprova.stardata.lan. 600 IN A 192.168.0.50
send

If you don’t have any errors, then you can delete the temp record:

$ nsupdate
> server localhost
> key dhcpupdate waZulpdc0rzMahbulbd34C==
> zone stardata.lan
> update delete provaprova.stardata.lan
> send

If you have any errors, check /var/log/syslog for error messages. I had a NOTZONE error first, because I was using stardata.lan instead of 0.168.192.in-addr.arpa as the zone for the PTR record. I had a SERVFAIL error due to AppArmor denying write permissions on zone files (you should not see this).

Back to DHCP configuration:

/etc/dhcp/dhcpd.conf

ddns-updates on;
ddns-domainname "stardata.lan";
ddns-update-style interim;

key dhcpupdate {
  algorithm hmac-md5;
  secret waZulpdc0rzMahbulbd34C==;
}

option domain-name "stardata.lan";
option domain-name-servers 192.168.0.2;
default-lease-time 7200;
max-lease-time 86400;
authoritative;
log-facility local7;

subnet 192.168.0.0 netmask 255.255.255.0 {
  range 192.168.0.130 192.168.0.149;
  option routers 192.168.0.2;
  option domain-name-servers 192.168.0.2;
}

zone 168.192.in-addr.arpa {
  primary ns.stardata.lan;
  key dhcpupdate;
}

zone stardata.lan {
  primary ns.stardata.lan;
  key dhcpupdate;
}

The ddns-* and the zone directives enable the DNS updating.

Sources: BIND 9 Server Howto, Dynamic DNS and DHCP – Easy tutorial.

Advertisements

8 thoughts on “Dynamic DNS updates for DHCP on Ubuntu 12.04

  1. Thank you for the article. It is clear and concise. I have read plenty of articles these days to make DHCP talk to DNS and update the entries in the zones. However, even following this article I still did not manage to see any updates in DNS (even though nsupdate does perfectly the job). It is also difficult to debug the problem because syslog does not show something wrong (no permissions errors appear). I would like to ask whether a .jnl file is expected to be created. If yes, does this happen after a client gets an IP from the DHCP ? Is there a way to find out why DHCP does not update DNS ? Any help or direction much appreciated as I am struggling at least one week now …

    • hello Kostas, if nsupdate is working, the problem should be on the DHCP side, maybe your clients aren’t identifying themselves properly?
      .jnl files are named binary journal for changes to the zones, there should be one for each zone (eg. direct and reverse zones) in /var/cache/bind/

      • Hello ! Thank you for your answer. I agree with you that the problem seems to be in the DHCP side. The clients did send their hostname (verified with wireshark) but still the .jnl was not updated. Since your message, I have read some articles discussing the client side configuration. I edited dhclient.conf and actually it updated the DNS (but not the reverse zone). It just seems a bit strange that one needs to configure each client. Is this a mandatory step ? I would expect the DHCP server to update the DNS itself. Am I missing something ? If configuring the client is important step why most guides miss describing this step ? Thank you for the advice. :)

      • Hello Kostas.
        From a quick look at man dhcpd.conf: if the client doesn’t provide a FQDN option, DHCP won’t update the PTR record, maybe that’s your problem.
        Can you provide more details about changes you did to dhclient.conf, which distro are you using on clients and maybe the wireshark dumps?

        Another thing, you can activate logging of DNS updates adding to your dhcpd.conf:

        logging {
          channel update_debug {
            file "/var/log/update-debug.log";
            severity  debug 3;
            print-category yes;
            print-severity yes;
            print-time     yes;
          };
          channel security_info    {
            file "/var/log/named-auth.info";
            severity  info;
            print-category yes;
            print-severity yes;
            print-time     yes;
          };
        
          category update { update_debug; };
          category security { security_info; };
        };
        

        You’ll need to create the files before restarting dhcpd.

  2. Hello. The changes I did in dhclient.conf are:

    send fqdn.fqdn “test2.mydomain.com”;
    send fqdn.encoded on;
    send fqdn.server-update off;
    also request fqdn, dhcp6.fqdn

    key DHCP_UPDATER {
    algorithm hmac-md5;
    secret yidYTwQ7zxt6lON2fmMfuA==;
    }

    zone mydomainname. {
    primary 192.168.1.1
    key DHCP_UPDATER;
    }

    # SAme as above for 1.168.192.in-addr.arpa (revrese)

    I got this from the man dhclient.conf but I first saw in http://www.linuxquestions.org/questions/linux-networking-3/dhclient-and-ddns-85031/

    Note that the forum above mentions having on the “send fqdn.server-update” option. The man says it depends. Have not checked with “on” .

    I noticed a change in Wireshark. The clients that have the above edit in /etc/dhcp/dhclient.conf ( I am using Ubuntu 11.04 on that client) also include the option Client Fully Qualified Domanin Name in the details of wireshark. If you do not include the above edit, the option is missing. So, you are right, it is expected from the client to provide a FQDN. However, in my case it updated the A records and not the PTR (reverse). I have not found the reason why yet.

    Is there an easy way to provide an FQDN in other OS’es ? If I have to do the above edit on each client, its the same as having to manually edit the DNS records anyway. Unless if there is an option to automatically provide FQDN and not having to edit the conf file for each client. In your case did you have to change anything on the client side ? I have tried to use Windows 8, Mountain Lion and Ubuntu and none worked. When I did the above changes in Ubuntu 11.04 it did finally update the A record.

    I have followed the log tips you mentioned above and this is what I got:

    12-Mar-2013 11:56:00.473 update: info: client 192.168.1.101#43573: updating zone ‘mydomain.com/IN’: adding an RR at ‘test2.mydomain.com’ A
    12-Mar-2013 11:56:00.478 update: info: client 192.168.1.101#43573: updating zone ‘mydomain.com/IN’: adding an RR at ‘test2.mydomain.com’ TXT
    12-Mar-2013 11:56:00.485 update: debug 3: client 192.168.1.101#43573: updating zone ‘mydomain.com/IN’: checking for NSEC3PARAM changes

    Hope I answer your questions.

    • Hello Kostas,

      I don’t have access to that lab at the moment so I’m shooting in the dark, but I didn’t change anything on client side. Also, if it doesn’t work with Windows and Macs, then it’s probably something on the DHCPd side.

      I found another tutorial using another keyword in the dhcpd.conf (after the ddns-domainname entry):

      ddns-rev-domainname "in-addr.arpa.";
      

      It’s worth a try.

      • Do you remember what OS your clients were using ? I had already used that option “dens-rev-domainname”.

        The deny/allow client-updates option made no difference. In both ways given that the dhclient.conf is edited as above, the A records are updated.

        If you have the chance it would be nice if I know whether the Client FQDN option is transmitted in the DHCP request from your client.

        Here is my dhcpd.conf file (cause I think its fine – removed public key):

        subnet 192.168.1.0 netmask 255.255.255.0 {
        authoritative;
        max-lease-time 604800;
        default-lease-time 86400;

        option subnet-mask 255.255.255.0;
        option broadcast-address 192.168.1.255;
        option domain-name “mydomain.com.”;
        option domain-name-servers 192.168.1.1;
        option routers 192.168.1.1;
        range 192.168.1.100 192.168.1.150;

        ddns-updates on;
        ddns-domainname “mydomain.com.”;
        ddns-rev-domainname “in-addr.arpa.”;
        ddns-update-style interim;

        deny client-updates;
        #option fqdn.server-update on;
        # include “/etc/bind/rndc.key”;

        key updatekey {
        algorithm hmac-md5;
        secret blahblah;
        }

        zone mydomain.com {
        primary 127.0.0.1;
        key updatekey;
        }

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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s