Combining DHCP and DNS
A rolling trip through getting your DHCP server and your DNS server talking to each other. Plus some discussion of DHCP on OS X.First of all if you're using Apple's built-in DHCP server this article isn't going to do much for you. To get all the hot sexiness of DHCP and DNS living in harmony you'll need to use another DHCP server. That means that you can kiss goodbye to Server Admin for doing your DHCP configuration, and probably DNS too. Once you've gotten past that, though, there isn't much more to this but doing some configuration.
At the end of all this you'll have a DHCP server that hands out leases to client machines, updates DNS after it has done so and you'll know more about debugging DHCP issues on OS X.
Install a new DHCP server
Apple's included DHCP server, bootpd, won't play nice with named the included DNS server. Luckily the same people that make the DNS server also make a DHCP server which is cake to install on OS X. (Ed. Note: This assumes you have Xcode installed.)
curl -O http://ftp.isc.org/isc/dhcp/dhcp-3.0.4.tar.gz gnutar -xzvf dhcp-3.0.4.tar.gz cd dhcp-3.0.4Now to build the package.
./configure make sudo make installThat was easy wasn't it?
Generate Update Keys
You need a secure way for your DHCP server to update your DNS server. To do that we'll generate a set of encryption keys that the two services will share. There's a couple of ways to do this. The first is to put the keys into a shared file that both the DNS and DHCP server can read, but it root readable only. You can also just put the keys directly into the config files for each of the services, but then you have to make the config files root readable only.
We're going to be taking the first path here.
So first generate the keys with the dnssec-keygen command. We'll be using the HMAC-MD5 hashing algorithm with 128 bits. You can make this be more secure with more bits..., but there isn't really that much point since you'll never be using this hash across the open internet. If you do intend to seperate your DNS and DHCP servers, then crank the 128 up to 512 if you want.
dnssec-keygen -a HMAC-MD5 -b 128 -n HOST DHCP-UPDATE-KEYThis will create two files with names like this: Kdhcp-update-key.+157+08239.key, and Kdhcp-update-key.+157+08239.private. They're essentially the same info in the files, and both in a format that we can't use. So take the value of the "Key" from the last line of the .key file. Which should be something similar to b6iMD3GvXMMg0x6uQILQYw==, in other words a big chunk of randomness and we're going to paste that into a new file. I like to stash the file in /var/named with the other DNS bits.
So create /var/named/dhcp-update.key and put the key into the file with a bit of surrounding info.
key DHCP-UPDATE-KEY {
algorithm hmac-md5;
secret b6iMD3GvXMMg0x6uQILQYw==;
};
Now, make sure the file is root-readable only.
chown root /var/named/dhcp-update.key chmod 700 /var/named/dhcp-update.keyAnd you're ready to move on to doing some configuration.
Configure the DHCP server
You need to generate a config file, /etc/dhcpd.conf, for the DHCP server.
Here's an annoted file to get you started. It's a decent idea to read through the dhcpd man page before emabarking on this.
# You need the next line or you won't actually be a DHCP server!
authoritative;
# DDNS stuff - these are the bits that get your DHCP server talking with your DNS server
ddns-update-style interim;
ddns-updates on;
ddns-ttl 600;
# put your real domain name here!
ddns-domainname "afp548.com";
# leave this as it, it takes care of the reverse records
ddns-rev-domainname "in-addr.arpa";
# You want your DHCP server to update DNS not the client machines
ignore client-updates;
# this is the file with your shared key in it
include "/var/named/dhcp-update.key";
# this generates a client's DNS name from the hostname the give or the leased IP address
ddns-hostname = pick-first-value(ddns-hostname, option host-name, binary-to-ascii(10,8, "-", leased-address));
# basic default DHCP info
max-lease-time 43200;
default-lease-time 43200;
# DNS servers for your clients to use
option domain-name-servers 10.0.129.25, 10.0.129.26;
# My Network - this is the set of addresses that you're handing out
subnet 10.0.129.0 netmask 255.255.255.0 {
option broadcast-address 10.0.129.255;
option subnet-mask 255.255.255.0;
option routers 10.0.129.1;
range 10.0.129.150 10.0.129.155;
}
# now the zone information for the updates
zone afp548.com.
{
primary 127.0.0.1;
# this key name matches the name you gave it in the key file
key DHCP-UPDATE-KEY;
}
zone 129.0.10.in-addr.arpa.
{
primary 127.0.0.1;
# this key name matches the name you gave it in the key file
key DHCP-UPDATE-KEY;
}
Finally you need to create a lease file for the server, or else dhcpd won't run.sudo touch /var/db/dhcpd.leases
Configure your DNS server for updates
Now to update /etc/named.conf to allow the DHCP server to use the shared encryption key to update the DNS zones.
Not too much to do here but add a few lines.
First you need a line to include the update key file so put this near the top.
include "/var/named/dhcp-update.key";Then for each DNS zone file that you want to update add this line to the zone definition.
allow-update { key DHCP-UPDATE-KEY; };
So a full zone declaration would look like this.
zone "afp548.com" in {
file "jodapro.com.zone";
type master;
allow-update { key cf1.jodapro.com; };
};
Time for a Little TestTime to light the fires and kick the tires. Start up named and dhcpd if they are not already running.
sudo named sudo dhcpdLook for any messages that appear in the terminal or in /var/log/system.log if things don't go right the first time.
Grab an OS X client and make sure you set a hostname in the Sharing preference pane in the System Preferences. This is what the client will send to the server and make a DNS entry out of. Once you have a lease test the forward and backward DNS resolution for the client.
Note that the DNS server will cache any DNS updates to a journal file. This only gets flushed to the actual zone files on disk every so often. So, be careful when making any direct changes to the zone files without first using rndc to flush them or stop the DNS server.
Debugging Things
The man pages for named and dhcpd will help you out here. However, there is a lot of information you can get on your client system too, although few people know to look for it.
For starters, after your system has acquired a lease you can find out what the client got by
ipconfig getpacket en0Just swap en0 for whatever interface you may be looking for DHCP information on. Of particular interest in this response is the server_identifier entry which tells you who your DHCP "daddy" is that gave you the lease. This is good for hunting down, and then ruthlessly beating, rogue DHCP servers on your network.
ipconfig goes further by allowing you to turn debugging on for the DHCP transaction.
ipconfig setverbose 1This will not only spew logs to /var/log/system.log but you can find the entire packet trace of the DHCP sequence in /var/log/com.apple.IPConfiguration.bootp. Swap the 1 with a 0 to turn it off when you're done.
Launchd!
Ed. Note: Josh points out that this plist is best placed in /Library not in /System.
Here's a launchd config file for the DHCP server. Put this in /Library/LaunchDaemons/org.isc.dhcpd.plist and then load it up with launchctl.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.isc.dhcpd</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/dhcpd</string>
<string>-q</string>
<string>-f</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceDescription</key>
<string>ISC DHCP Server</string>
</dict>
</plist>
Shameless Book PlugWhile it's a hard book to find, and it's not a real exciting read some times, the DHCP Handbook is by far the best DHCP reference that I have found. It specifically has an entire chapter on DHCP and DNS interaction, among much much more esoteric DHCP information.
