Hack21.Integrate DHCP and DNS with Dynamic DNS Updates


Hack 21. Integrate DHCP and DNS with Dynamic DNS Updates

Assign dynamic hostnames and IP addresses, and update your DNS server to reflect changes with no administrative intervention or scripted hacks.

If any two services are begging to be integrated, it's BIND and DHCP. Dynamically assigning IP addresses with DHCP isn't so useful if it makes your DNS zone information obsolete! Imagine if all of your configured printers got dynamically assigned IP addresses from your DHCP server. The next time your default printer got a new IP address from the DHCP server, addressing that host by name could return an unexpected result from DNS, because they're not in sync. Where your print job winds up could be anybody's guess.

With older versions of the ISC DHCP server and BIND, this problem was solved in one of two ways. First, you could just tell your DHCP server to statically assign addresses to your hosts [Hack #20]. This is still a useful solution to the problem, especially if the DHCP server delivers information besides an IP address, such as which NTP servers and NIS servers to use. The second option is to grab a tool (or script one yourself) to perform DNS updates.

In more recent versions of DHCP and BIND, both services support a mechanism for performing dynamic DNS updates (defined in RFC 2136), whereby an authorized user can add and delete records from forward and reverse zone files. Recent versions of DHCP also support a more flexible mechanism for deriving a dynamic hostname from an expression, which can include data sent from the client in the DHCP request.

Add these together, and you have the ability to, for example, maintain a dynamic address pool that also assigns hostnames dynamically and then updates the DNS server to reflect the changes. The alternative to dynamic hostnames is to have the DHCP server use the hostname supplied by the client, but depending on the environment, this may not be desirable. In situations where there are frequent visitors from random places, hostname overlapping can cause DNS updates to fail. Also, it's not always safe to assume that a client will supply a valid hostname (or any hostname, for that matter).

Let's go over how to get DHCP and BIND to work together to perform dynamic DNS updates.

The very first step that needs to be performed is the generation of a key that the two services will use to communicate with each other. The DHCP server uses this key to sign update requests sent to the DNS server, and the DNS server uses it to verify the signed requests from the DHCP server. BIND 9 comes with a utility to generate this key, called dnssec-keygen. You need to make three decisions about how to run the key-generation command. The first is the name of the key, the second is the number of bits used in the key's encryption, and the third is what form the name of the key will take.

Let's have a look at a key generated to represent the host that's allowed to perform the updates. We'll make it 512 bytes long, and we'll name the key using the fully qualified domain name (FQDN) of the host. Here's the command:

 # dnssec-keygen -a  HMAC-MD5  -b 512 -n HOST  apollo.linuxlaboratory.org . 

This generates a TSIG key and places it in a file in the current directory. The file is named K<keyname>+157+<uniqueid>.private. The contents of this file will be something similar to this:

 Private-key-format: v1.2 Algorithm: 157 (HMAC_MD5) Key: y3v81k9O9z6c62KgPNlik8P6QZIEB3yb/Blw/ XE8QN46RLeC4XkptJiRA56roCcCEGSAdCJb5kmM2/S7MBrmRQ== 

The important part here is the long value after the Key keyword. Once you have this value copied to the proper places in your configuration files, you can get rid of the key files themselves.

3.3.1. Configuring the BIND 9 Name Server

The next step is to configure BIND to allow updates from the DHCP server, using the key you just generated. We do this step before configuring DHCP to avoid lots of log entries indicating failed update attempts from the DHCP server during the lag time between completing the configuration of both services.

The BIND server's named.conf file will need to have its zone blocks altered to contain an update-policy block, which lets the server know which keys can update what records in which zones. First, we need to tell the server about all the keys we want it to know about. In our simple setup we only have one, but some environments may have one key for each host that might be allowed to alter its own records. Here's a simple block that we can add near the top of the named.conf file to inform the server of our key:

 key apollo.linuxlaboratory.org. { algorithm hmac-md5; secret "y3v81k9O9z6c62KgPNlik8P6QZIEB3yb/Blw/ XE8QN46RLeC4XkptJiRA56roCcCEGSAdCJb5kmM2/S7MBrmRQ=="; }; 

Next, we need to reference this key in our update-policy substatements in each zone for which the key is valid. Here's a typical zone that has been altered to accept updates using this key:

 zone "linuxlaboratory.org" in { type master; file "db.linuxlaboratory.org"; update-policy { grant apollo.linuxlaboratory.org. subdomain linuxlaboratory.org. ANY; }; }; 

Here, our update policy says to allow updates signed with the key apollo.linuxlaboratory.org., as long as the update is affecting an entry that is a subdomain of linuxlaboratory.org.. Note that the subdomain keyword includes the hostname. Also, we allow this key to update any record type, by including the keyword ANY on the end. This doesn't really mean literally any record type, though: it'll never update, for example, your SOA records! If you want to be explicit, you can list the record types (for example, A PTR would allow updates only to those record types).

For completeness, here's the reverse zone block, altered with a similar update-policy statement:

 zone "42.168.192.in-addr.arpa" in { type master; file "db.192.168.42"; update-policy { grant apollo.linuxlaboratory.org. subdomain 42.168.192.in-addr.arpa ANY; }; }; 

Both zones allow updates to any record type of any host in the zone. This effectively makes our DHCP server the "sole master" host for performing updates.

3.3.2. Configuring the ISC DHCP Server

Now let's move on to configuring our DHCP server. In our example environment, we have a lot of hosts grabbing static IP addresses from our DHCP server. We'll also set aside a range to be assigned to visitors, who will also be assigned dynamic hostnames. This information will be sent to the DNS server, and the requests will be signed with the same key we used in the BIND configuration.

To get the configuration right, we'll need to add a few extra settings to the global section of the file to tell the server to do dynamic updates. We'll then define the key to use a block very similar to the one we put in our named.conf file. Here's the first part of our newly updated dhcpd.conf file:

 ddns-update-style interim; deny client-updates; authoritative; option domain-name "linuxlaboratory.org"; option domain-name-servers 192.168.42.3; option subnet-mask 255.255.255.0; default-lease-time 600; max-lease-time 7200; key apollo.protocolostomy.pvt. { algorithm hmac-md5; secret "y3v81k9O9z6c62KgPNlik8P6QZIEB3yb/Blw/ XE8QN46RLeC4XkptJiRA56roCcCEGSAdCJb5kmM2/S7MBrmRQ=="; } 

The first two settings relate directly to our goal. ddns-update-style is set to the only value that allows us to perform DNS updates in newer versions of BIND. There used to be an ad-hoc value that was valid here, which represented a different mechanism for performing updates, but in newer versions this value is ignored and will not work. The other valid value here is none, which is used to explicitly state that the server will not perform updates. You must specify a value for the ddns-update-style setting on Red Hatbased distributions.

The next setting (deny client-updates;) tells the server to deny any requests that clients may send to update their own information. We've set this explicitly because we'll be assigning dynamic hostnames. If we do not set this, the server will try to use the hostname supplied by the client, which can cause problems in some environments.

The next new part of this file is the block that defines the key to use to sign updates before shipping them over to the DNS server. It is almost identical to the DNS server configuration file, and it performs the exact same function.

Once these settings are in place, the next thing to do is define which zones our DHCP server will attempt to update, on which servers, and using which keys. Here are the zone blocks in our dhcpd.conf file that we'll need to get things working:

 zone linuxlaboratory.org. { primary 127.0.0.1; key apollo.linuxlaboratory.org.; } zone 42.168.192.in-addr.arpa. { primary 127.0.0.1; key apollo.linuxlaboratory.org.; } 

These, of course, must be valid zones on the DNS server listed as primary in each block. In our case, the DNS server is on the local host, so the updates are performed over the local loopback interface and are signed with the key we created earlier.

The last step is to set up dynamic hostnames for visitors, who will get IP addresses from a predefined range. Here's a configuration block to take care of that:

 subnet 192.168.42.0 netmask 255.255.255.0 { range 192.168.42.85 192.168.42.99; option broadcast-address 192.168.42.255; option routers 192.168.42.1; ddns-hostname = concat ("dhcp-", binary-to-ascii (10, 8, "-", leased address)); } 

Visitors on our subnet are assigned addresses between node numbers 85 and 99, inclusive. The hostname the DHCP server will send to the DNS server is defined using the ddns-hostname option. The value that results from the expression, for the host that is leased the address 192.168.42.99, will be "dhcp-192-168-42-99.linuxlaboratory.org". The first argument to concat is a static string. The second is the binary-to-ascii function. The arguments to that function, in order, are the base to use (10 is simple, familiar, decimal numbers), the width of each value (8 bits), the separator to place after each 8-bit value (a dash), and the value to act upon, which in this case is a variable defined by the server. There are many wild schemes for assigning host-names, but this one has served me well and is very simple.

3.3.3. Starting the Services and Troubleshooting

Restart the named server, and then restart the dhcp server. Both should start without errorif you run into one, it's likely to be a forgotten comma or a misplaced curly brace or parenthesis. If they both start without errors you'll at least know that your configuration is syntactically correct, so let's move on to some other things you might see in the logs.

One of the most common issues revolves around the key and how it is generated and used. You might see messages like these:

 Sep 3 13:06:11 apollo dhcpd: DHCPDISCOVER from 00:e0:b8:5c:46:c6 via eth0 Sep 3 13:06:12 apollo dhcpd: DHCPOFFER on 192.168.42.99 to 00:e0:b8:5c:46: c6 (moocow) via eth0 Sep 3 13:06:12 apollo named[13005]: client 127.0.0.1#32880: request has invalid signature: TSIG DDNS_UPD: tsig verify failure (BADKEY) Sep 3 13:06:12 apollo dhcpd: Unable to add forward map from moocow. linuxlaboratory.org to 192.168.42.99: bad DNS key 

More than one issue can cause these messages. For example, you might simply have mistyped the key. Make sure you have quoted strings where you need them, both in the key's value and in the name of the key. Use the examples above to guide you, as they're taken from a known working configuration. If that doesn't work, consult the manpages for the configuration files themselves to make sure you got it right.

Another reason you might get these messages is because either you used an invalid name when generating the key, or you generated the wrong key type. For example, if you ran the dnssec-keygen command with -n USER and then named the key after the host allowed to perform the update, the key won't work to validate either a user or a host. You'll also be in hot water if you generated the key with -n HOST but didn't name the key after the host. Generating the key using the method we used in this example will get you rolling in no time.

Most other issues are caused by pretty blatant configuration typos or permissions issues. For example, when BIND accepts an update from the DHCP server, it doesn't rewrite its zone files immediately. It generally updates them once an hour, and in the interim, it keeps the data in a journal file. If the journal file doesn't exist, the user that named is running as needs to have permission to write to the directory where the journal files will live.

When all is well, the logs generated by a successful setup will look similar to this:

 Sep 3 15:07:55 apollo dhcpd: DHCPDISCOVER from 00:0c:f1:d6:3f:32 via eth0 Sep 3 15:07:55 apollo dhcpd: DHCPOFFER on 192.168.42.98 to 00:0c:f1:d6:3f: 32 (livid) via eth0 Sep 3 15:07:55 apollo named[14931]: client 127.0.0.1#32907: updating zone 'linuxlaboratory.org/IN': adding an RR at 'dhcp-192-168-42-98. linuxlaboratory.org' A Sep 3 15:07:55 apollo named[14931]: client 127.0.0.1#32907: updating zone 'linuxlaboratory.org/IN': adding an RR at 'dhcp-192-168-42-98. linuxlaboratory.org' TXT Sep 3 15:07:55 apollo named[14931]: zone linuxlaboratory.org/IN: sending notifies (serial 8) Sep 3 15:07:55 apollo dhcpd: Added new forward map from dhcp-192-168-42-98. linuxlaboratory.org to 192.168.42.98 Sep 3 15:07:55 apollo named[14931]: client 127.0.0.1#32907: updating zone '42.168.192.in-addr.arpa/IN': deleting rrset at '98.42.168.192.in-addr.arpa' PTR Sep 3 15:07:55 apollo named[14931]: client 127.0.0.1#32907: updating zone '42.168.192.in-addr.arpa/IN': adding an RR at '98.42.168.192.in-addr.arpa' PTR Sep 3 15:07:55 apollo named[14931]: zone 42.168.192.in-addr.arpa/IN: sending notifies (serial 6) Sep 3 15:07:55 apollo named[14931]: client 192.168.42.3#32903: received notify for zone 'linuxlaboratory.org' Sep 3 15:07:55 apollo dhcpd: added reverse map from 98.42.168.192.in-addr. arpa. to dhcp-192-168-42-98.linuxlaboratory.org Sep 3 15:07:55 apollo dhcpd: DHCPREQUEST for 192.168.42.98 (192.168.42.3) from 00:0c:f1:d6:3f:32 (livid) via eth0 Sep 3 15:07:55 apollo dhcpd: DHCPACK on 192.168.42.98 to 00:0c:f1:d6:3f:32 (livid) via eth0 

3.3.4. See Also

  • "Quick and Easy DHCP Setup" [Hack #20]



Linux Server Hacks (Vol. 2)
BSD Sockets Programming from a Multi-Language Perspective (Programming Series)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 162
Authors: M. Tim Jones

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net