Search this site


Metadata

Articles

Projects

Presentations

Dynamic DNS and DHCP - Easy to do, and you'll thank yourself later

Preface

This article will cover how to setup dns with dynamic updates aswell as configuring your dhcp server to push updates to it aswell.

I assume you already know how to setup plain old dns aswell as plain old dhcp. This is not an introduction to either of those. I used BIND 9 and ISC DHCPD v3 for this article.

If there's anything this article doesn't cover with respect to what you are looking for, leave a comment and I'll do what I can.

What is Dynamic DNS?

Dynamic DNS is the means by which to push new records into your dns server while it is running, without having to edit any zone files. It is quite often coupled with dhcp to provide dynamic network services that have hostnames follow the appropriate machines around.

Dynamic DNS

Setting up dynamic dns is pretty straight forward. To do it securely, you need to first create a secret key. This secret key will be used to authenticate our dns update clients with the dns server. Luckily for us, there's a tool that'll do that for us.

Create a dnssec key

That tool is called dnssec-keygen. Don't feel like reading the manpage? Fine. dnssec-keygen is a tool to create dnssec keys, much like ssh-keygen creates ssh keys. Pick a name for your key, it can be any name. I usually name it appropriately. For this example, I will call our key dhcpupdate.

Create the key as such:
% dnssec-keygen -a hmac-md5 -b 128 -n USER dhcpupdate
Kdhcpupdate.+157+14638
        
This will create a 128bit HMAC-MD5 keyfile called dhcpupdate.

The output is the file prefix. If you do ls Kdhcpupdate* you will see two files. The .key file is most useful, in my opinion. Looking at the .key file:
dhcpupdate. IN KEY 0 3 157 N8Hk2RUFO84bEVl3uGTD2A==
No, that is not the key I use. No, you shouldn't use that key for your server ;)

The last token in that file is the key (N8Hk...). Keep that secret. Forever.

named.conf changes

The updates to named.conf are pretty straightforward. For every zone you want to allow dynamic updates (for this specific key), you need to add an allow-update section. First, you'll want to add a key section. The following goes in the global portion of your named.conf:
key dhcpupdate {
  algorithm hmac-md5;
  secret "YOURKEYGOESHERE";
  # example:
  # secret "N8Hk2RUFO84bEVl3uGTD2A==";
};
Simple enough. Just remember that it goes in quotes!

Next, we need to add allow-update entries to all zones we would like to update. Let's say I have two zones:
  • home
  • 0.168.192.in-addr.arpa
In my named.conf, I'll want to add the following to those zone declarations:
allow-update { key dhcpupdate; };
For example:
zone "home" {
  type master;
  file "master/db-home"
  allow-update { key dhcpupdate; };
};

zone "0.168.192.in-addr.arpa" {
  type master;
  file "master/db-home_rev";
  allow-update { key dhcpupdate; };
};
That's all we have to do. Restart named and you should be able to push updates dynamically to the dns server.

Testing with nsupdate

nsupdate is the tool we'll be using to test if we have setup the server correctly. nsupdate takes commands like nslookup does, if run without arguments:
nightfall(~/t) % nsupdate
> 
The following commands are good to know:
server [server address]
Sets the target server for who to send updates
key [keyname] [secret]
Tell nsupdate what your key is
zone [zonename]
Explicitly choose a zone to send updates for. If unspecified, nsupdate will guess.
update [...]
Request an update to record
send
Send updates
show
Show updates that haven't been sent
update will not update the dns server automatically. It will queue the update request until you tell nsupdate to send.

For this example, my dns server is dns.home:
% nsupdate
> server dns.home
> key dhcpupdate N8Hk2RUFO84bEVl3uGTD2A==
> zone home
> update add 50.0.168.192.in-addr.arpa 600 IN PTR happynode.home.
> send
> update add happynode.home. 600 IN A 192.168.0.50
> send
If all goes well, there will be nothing printed after you type send. Let's check that we've added it!
% host happynode.home
happynode.home has address 192.168.0.50
% host 192.168.0.50
50.0.168.192.in-addr.arpa domain name pointer happynode.home.
You can delete entries from dns with (for example):
update delete happynode.home
However, if something went wrong:
update failed: NOTZONE
You didn't specify a hostname the dns server has zone information for. Make sure you're using a full domain name. That is, do not use happynode. Use happynode.home.
; TSIG error with server: tsig indicates error
update failed: NOTAUTH(BADSIG)
You are providing the wrong key, or the server is refusing your key for another reason?
update failed: SERVFAIL
The number one cause for this error (for me) is permissions in the directory of your zonefile. Dynamic updates will create a journal file as: /etc/namedb/home/home.jnl (or wherever your zonefile is). If the user named is running as cannot create files in /etc/namedb/home then it will fail. This error should show up as 'permission denied' errors in the logs with a reference to what file it is trying to create.
Worst case, run named with a high debug level. Also, don't reload named, restart named when debugging. Reloading doesn't reinitialize some things.

DHCPD

A few minor changes are necesary to your dhcpd.conf (isc dhcp3 server). First, in the global portion:
ddns-update-style interim;

# If you have fixed-address entries you want to use dynamic dns
update-static-leases on;
Furthermore, you need to tell dhcpd.conf about the dnssec key and zone information. The following still goes in your dhcpd.conf:
key dhcpupdate {
  algorithm hmac-md5
  secret N8Hk2RUFO84bEVl3uGTD2A==;
}

zone 0.168.192.in-addr.arpa {
  primary dns.home;
  key dhcpupdate;
}

zone 10.168.192.in-addr.arpa {
  primary dns.home;
  key dhcpupdate;
}

zone home {
  primary dns;
  key dhcpupdater;
}
*NOTE!* Notice that the secret is entered WITHOUT QUOTES. Doing so with quotes is a syntax error. If you see errors about invalid base64 characters, this is likely the reason.

The primary values are the primary dns server entries so dhcpd knows where to send updates. In this case, my primary dns is dns.home. Yours will obviously vary, as your key should vary.

Next, I'll show you a few different examples.
Sample entry without fixed-address (roamer)
host happylaptop {
  hardware ethernet 00:0a:39:22:da:39;
  option host-name "happylaptop";
  option domain-name "home";
  ddns-hostname "happylaptop";
  ddns-domain-name "home";
}
When happylaptop requests an address via dhcp, the dhcp server will tell the dns server. Specifically, it will push forward (A) and reverse (PTR) lookup entries. Excellent. Now I can access my laptop from the network without having to lookup, find, or discover it's IP address, becuase I can simply point at happylaptop.home and it resolves to my laptop, wherever it is.
Sample entry set with 'group'
group {
  option domain-name "home";
  ddns-domainname "home";

  host happylaptop {
    hardware ethernet 00:0a:39:22:da:39;
    option host-name "happylaptop";
    ddns-hostname "happylaptop";
  }

  host dellstation  {
    hardware ethernet 00:b1:48:2a:ad:9c;
    option host-name "dellstation";
    ddns-hostname "dellstation";
  }
}
Sample fixed-address
host jukebox {
  hardware ethernet 01:d0:06:b8:68:34;
  fixed-address 192.168.0.5;
  ddns-hostname "jukebox";
  ddns-domain-name "home";
  option host-name "jukebox";
  option domain-name "home";
}
That should be a decent set of examples.

dhcpd.conf caveats

  1. The option, use-host-decl-names does NOTHING (it seems?) to aid in automatic specification of ddns-hostname. This sucks. If you find otherwise, let me know.
  2. You must specify ddns-hostname and ddns-domainame. dhcpd will not "figure it out" if you just specify host-name and domain-name.
  3. I don't know how to get dynamic-generated roamer addresses working, if it's possible. That is, I want to specify a range of roamers in 192.168.0.160/27, and want dhcpd to autogenerate dns names for those based on a given pattern. Possible? Perhaps not.

My example config files


37 responses to 'Dynamic DNS and DHCP - Easy to do, and you'll thank yourself later'

Showing last 15 comments... (Click here to view all comments)

Jordan Sissel wrote at Sat Jul 26 13:39:57 2008...
WHat about it is illegal? 192.168.0.160 with netmask 255.255.255.224 (/27) seems legal enough.

Jordan Sissel wrote at Sat Jul 26 13:42:15 2008...
I tried that in my dhcpd.conf, and it worked fine.
subnet 192.168.0.160 netmask 255.255.255.224 {
range 192.168.0.160 192.168.0.191;
option broadcast-address 192.168.0.255;
option routers 192.168.0.160;
ddns-hostname = concat ("dhcp-", binary-to-ascii (10, 8, "-", leased-address));
}


Works just fine! :)

Jones wrote at Wed Sep 3 17:28:02 2008...
Will you indulged a newbie question?  I think i'm having a concept problem with this approach.

Is the DHCPD server supposed to assign the client a hostname or do we already expect the client to know its hostname and match the DHCP configuration?  I've tried part of this example and have setup my own DHCPD server...but i'm noticing that DHCPD, while DHCPD is certainly giving my RHEL5 client something (my prompt changes), RHEL 5 is not updating itself accordingly.  For example, the /etc/hosts file does not contain this new hostname.

Is this the expected behavior?

Thanks

James wrote at Fri Oct 17 15:24:54 2008...
Perfect! Was looking for a straightforward howto and this was it. Thanks for sharing.

Feroze. K. M wrote at Fri Oct 24 22:54:32 2008...
Please help me out.
I am getting the following error in my /var/log/messages.

"dhcpd: Unable to add forward map from abc.example.com to 192.168.0.100: bad DNS key"

Feroze. K. M wrote at Sat Oct 25 01:28:13 2008...
Please help me out.
I am getting the following error in my /var/log/messages.

"dhcpd: Unable to add forward map from abc.example.com to 192.168.0.100: bad DNS key"

whitehat237 wrote at Tue Nov 25 16:08:36 2008...
This worked just fine for me.  There were a couple things I needed to change from the post above.

1. algorithm, was set to md5 not mdd5

2. I could not use nsupdate to update the record.  I kept getting NOTZONE, however clients using DHCP, were able to create the reverse record with no issues.  (The most important part for me anyway)

3. The example dhcpd.conf block has an error:

zone home {
  primary dns;
  key dhcp_updater;
}


The last line should read dhcpupdate not dhcp_updater

Damien wrote at Tue Feb 10 00:03:15 2009...
Using nsupdate works fine. However these are the errors I am trying to fix:

Feb 10 08:28:58 gateway named[32540]: client 192.168.49.1#52396: updating zone '
49.168.192.in-addr.arpa/IN': adding an RR at '149.49.168.192.49.168.192.IN-ADDR.
ARPA' PTR
Feb 10 08:28:58 gateway dhcpd: added reverse map from 149.49.168.192.49.168.192.
in-addr.arpa to ESPRIMO.opm.local

It should not write the subnet address twice. I don't know how to fix this - is it a dhcpd config or named ?

Damien wrote at Wed Feb 11 00:22:01 2009...
Fixed the problem!
I have written my zone files by hand while reading some forum about DNS configuration for Ubuntu. It stated to put the "ORIGIN <domain>" declaration at the top of the zone file - that is what caused the doubling of the subnet address. I just removed the "ORIGIN" declaration.
Thanks for all the info. I previously didn't know nsupdate even existed.

arth1 wrote at Sun Feb 15 12:10:05 2009...
(Damien:  No, the presence of the $ORIGIN statement isn't what caused the doubling.  Your botching of it is.  The #1 error people do when configuring named zone files is to leave out the traling dot in domain names.  It is significant -- it terminates the domain, and if you drop it, the current domain name will be tacked onto the end.  This usually manifests as a doubling of the domain name.)

Anyhow, I wish I could get dhcpd to add more than A records when updating the DNS, or, alternatively, add an A (and TXT) entry even when there are other non-A records present.  In particular, I would like to add MX, SSHFP and RP entries for dynamic hosts (or have these entries persist without an A record).  As it is if you have an MX record for a hostname, dhcpcd refuses to update the DNS with the A record, with an erroneous error message saying that the A record already exist and isn't ours.  It appears it checks for ANY entry instead of A.

Anyone know whether it's possible to trick dhcpd to update more than A records?  With trusted hosts, I can always use nsupdate from the host itself, but for untrusted hosts, that's not an option.

Jordan Sissel wrote at Sun Feb 15 14:09:51 2009...
@arth1: I think your best bet is to have a script watch the leases file for your dhcp server and act accordingly. Alternatives include patching isc-dhcpd to do what you need or trying an alternative dhcp server.

abdulla.pcp wrote at Mon Jun 1 23:50:36 2009...
supper notes

Scott gutman wrote at Mon Jul 13 10:20:46 2009...
thank you

Scott Gutman wrote at Mon Jul 13 14:21:31 2009...
For newbies, let me save you some hair!!

1. Please note that there is a 15min delay when using dynamic updates to populate the zone files. The information is first cached in jnl files in the dir of the zone files.  So after you use nsupdate, you need to wait, wait, wait.... Or you can stop and start bind to flush the changes, but you will see the file size of the jnl files increase.

2. In the nsupdate example please note there is a missing and incorrect zone statement.  The first zone statement should have been:
  zone 0.168.192.in-addr.arpa
and the 2nd:
  zone home
these should be placed just before the update statement.

3. If you are using webmin (like myself) be aware that the rndc generator key name changes.  The key name in the named.conf is rndc-key and rndckey in the rndc.conf. this might be a problem if you use include statments in your named.conf.

Bill Taylor wrote at Thu Jul 16 08:39:28 2009...
Where might I find ISC DHCP v3 for Centos 4.7 I have googled it and not been able to find it.

Thanks


Leave a reply

You need javascript enabled to use this form. Anti-spam efforts ongoing. Also, if the comment doesn't show up, it's because the form expired. Go back and copy your comment, reload the form, and resubmit. Apologies if this is a hassle, I'm just playing with antispam methods right now. If this insists on not working, please email me about it.

Name (required)
E-mail (optional, if you want me to be able to email you back)
URL (also optional)
Comment: