Tools dhcpy6d Lead image: Lead Image © Paul Herbert, 123RF.com
Lead Image © Paul Herbert, 123RF.com
 

Exploring dhcpy6d, a DHCP server for IPv6 networks

Not Just Addresses

Even if you don't have to have DHCP on your IPv6 network, you might want it anyway. Dhcpy6d is a promising DHCP option for IPv6. By Konstantin Agouros

The auto-configuration mechanisms built into IPv6 mean you don't necessarily need a DHCP server in order to avoid the cumbersome task of manual address configuration. However, modern DHCP servers don't just hand out addresses. Unless you're using some special extensions or add-on services, the native auto-configuration features of IPv6 won't configure important settings such as the DNS server, so, in practical terms, a DHCP server is still required for larger networks.

RFC 3315 [1], which appeared in July 2013, defines the DHCPv6 protocol. As you can imagine, the long IPv6 addresses and other changes to the protocol, such as the preference for multicast versus broadcast addresses, result in significant changes to the DHCP service. Even the DHCP ports are different with IPv6 (UDP 546 with the client; 547 with the server).

Several options are available for DHCP in IPv6, including Dibbler [2], Internet Systems Consortium (ISC) DHCPv6 [3], and WIDE-DHCPv6 [4], and each has a slightly different approach to a very perplexing problem.

What completely messes up the existing concept of IP address allocation is a parameter called the DHCP Unique Identifier (DUID), which all DHCPv6 clients compute during the first call and then store in a file. According to Paragraph 9 of RFC 3315, the DUID is the only characteristic by which a server can recognize its clients – and vice versa. The RFC even says in the RFC that: "Clients and servers MAY NOT interpret DUIDs in any other way."

The DUID can be generated three ways:

The link layer address might sound like a MAC address, but it isn't. According to the RFC, "This type of DUID consists of two octets containing the DUID type 3, a two-octet network hardware type code, followed by the link layer address of any one network interface that is permanently connected to the client or server device." In other words, the DUID refers to a device and is not (solely and uniquely) a feature of a network card's MAC address (Figure 1).

To form an IPv6 address ID from the MAC address, FFFE is inserted and the second bit is flipped in the first byte.
Figure 1: To form an IPv6 address ID from the MAC address, FFFE is inserted and the second bit is flipped in the first byte.

The Layer 3 ICMPv6 protocol discovers the hardware address information in the IPv6 world, a task assigned to the Layer 2 Address Resolution Protocol (ARP) in IPv4. The process of discovering devices in IPv6 is known as the Neighbor Discovery Protocol (NDP) [5]. The formal approach without the static link to the MAC address might appear clever at first because it means that a device on the network is equally identifiable on all interfaces. However, the approach used in IPv6 leads to problems in a virtualized world as soon as the administrator clones a device. All copies of the master have the same address when you clone a virtual machine because the DHCPv6 server thinks they are the same machine. On a positive note, administrators don't have to make any changes to the DHCP configuration after replacing a network card.

Non-Compliant

The Institute for Solid State and Materials Research in Dresden, Germany, had a network management tool based on unique allocation of MAC addresses to IP addresses. The first experiments with IPv6 in 2009 made Henri Wahl, who worked at the Institute, realize that automatic configuration via the distributed prefixes was not enough. Wahl started to develop dhcpy6d. As the name indicates, the tool is written in Python. After a few years of work at the Institute, Wahl released the software in 2012 [6]. You can download the source code from GitHub or obtain it from the project's home page [7].

Dhcpy6d intentionally violates the requirements of RFC 3315. Other tools, such as the ISC DHCP daemon, now support the option of extracting the MAC address from the client's DUID in order to allow a configuration based on the MAC address. Dhcpy6d takes the opposite approach. If a new MAC address but the old DUID are used after a change of hardware, everything will still work and the connection between the MAC and IP is lifted. In addition to identifying by MAC address, dhcpy6d also allows identification via the DUID, as intended by the RFC.

Dhcpy6d Sorting Logic

Dhcpy6d assigns configurations based on classes, address ranges, and clients. A class determines parameters that apply to a group of clients; for example, the name server and the default router. Whether or not a client belongs to a class is defined explicitly in the client configuration or else by filtering by hostnames, MAC addresses, or DUIDs (with Python regular expressions).

As a final parameter for organizing clients in classes, dhcpy6d uses the interface as follows: All requests that arrive via network card 1 are Class A, and all of those that arrive via NIC 2 belong to Class B. This approach assumes dhcpy6d has a foothold in each relevant network. Dhcpy6d does not provide a means for allocating network ranges via a DHCPv6 relay.

A client describes a single device; administrators can assign the client a hostname and an explicit address. What is important is that the client's definition states the class to which the client belongs. All clients that are not explicitly listed are put in the default class, and the parameters that dhcpy6d uses for this class automatically apply.

The address range contains the template the DHCP server uses to allocate IPv6 addresses for a class. For the address range 2001:db8::$mac$, for example, it simply appends the client's MAC address to the 2001:db8::/64 prefix. Mappings between class and address range are one to many – members of a class can be allocated addresses from multiple address ranges.

For each address range, dhcpy6d defines how long the mapping should apply, whether the system will receive DNS updates, and in which zones the client is registered.

Installation and Setup

Dhcpy6d runs on Linux, FreeBSD, NetBSD, OpenBSD, and Apple OS X. I used the version from the Git repository on Gentoo Linux for this article. The dhcpy6d website [7] offers downloadable packages for RPM- and Deb-based distributions. Version 2.6 of the software (2.7 is better) requires Python and the dnspython package for updating the name server, as well as the Python MySQL module if MySQL is used as the database. If SQLite is used instead, you need to install the corresponding package and Python support.

You'll also need a few external script files containing modules. After running git clone, you can run the software directly in the directory. Use the python2.7 binary to make sure you're really using Python 2.7.

Dhcpy6d saves the leases in a SQLite or MySQL database. A supplied SQL file is used to initialize the tables. The command

sqllite volatile.db < doc/volatile.sql

generates the SQLite database. The project website describes how to install both the MySQL databases and client lists.

Advertising a Server

Before clients on a LAN segment even start trying to obtain their addresses and configurations via DHCPv6, they first need to know that a DHCPv6 server available on their network. A client that activates its IPv6 configuration first sends a router solicitation. The client then receives a response from the router (or routers). An Unmanaged flag in the prefix of the response (router advertisement) prompts the client to build its own address from the prefix (using the EUI-64, 64-bit extended unique identifier method [8] or a random method for anonymous addresses).

If the flag is set to Managed, the DHCPv6 process initiates. The router on the network on which dhcpy6d is running needs to use this Managed flag in its advertisements. The project website suggests the following configuration for the widespread radvd (Linux IPv6 router advertisement daemon) [9]:

interface eth0 {
AdvSendAdvert on;
AdvManagedFlag on;
};

Radvd should not announce the prefix explicitly.

The dhcpy6d.conf file

Dhcpy6d maps the described logic in two configuration files: dhcpy6d.conf and client.conf. The client.conf file contains the entries for the clients, although a relational database will do fine.

The dhcpy6d.conf file is divided into sections with names in square brackets. The [dhcpy6d] block collects the general configuration parameters. Listing 1 shows the dhcpy6d.conf file used in our lab. Line 2 specifies the interface on which the service operates. Multiple space-separated entries are possible.

Listing 1: dhcpy6d.conf

01 [dhcpy6d]
02 interface = eth1
03
04 store_config = file
05 store_file_config = ./client.conf
06
07 store_volatile = sqlite
08 store_sqlite_volatile = ./volatile.sqlite
09
10 log = on
11 log_file = ./dhcpy6d.log
12
13 really_do_it = yes
14
15 dns_update = yes
16 dns_update_nameserver = 2001:db8:5::1
17 dns_rndc_key = rndc-key
18 dns_rndc_secret = FmZGJuHr/4+LkuxBc628Qg==
19 dns_use_client_hostname = no
20 domain_search_list = lmtest
21
22 [address_default]
23 category = mac
24 pattern = 2001:db8:1::$mac$
25
26 [address_special]
27 category = mac
28 pattern = 2001:db8::$mac$
29 dns_update = yes
30 dns_zone = lmtest
31 dns_rev_zone = 8.b.d.0.1.0.0.2.ip6.arpa
32
33 [class_special]
34 addresses = special
35 nameserver = 2001:db8:5::1

Lines 4 and 5 determine where the client definitions reside and define their format as text files (file). If you specify none for store_volatile, you will prevent dhcpy6d from processing individual clients. In addition to file, sqlite and mysql are also possible. Lines 10 and 11 specify where the service should write its logfile. If you were to set the log_console parameter to on, dhcpy6d would log directly to stdout. Line 13 is very important; you mustn't forget to switch the service on.

The block in lines 15 to 19 dictates the parameters for entering the clients in a name server. The last parameter specifies that the hostname sent by the client is not used, but a hostname from the client.conf file is used instead. Unfortunately, you can only globally specify the list of DNS domains in which a client should search, rather than specifying the class.

The [address_default] block specifies a network block to which dhcpy6d appends the MAC address. In addition to the mac category, other options are also possible:

The second address block in lines 26 to 31 determines that a DNS update should take place, and the forward and reverse zones are specified. The entry in line 34 must match the name of the address range – several ranges are also possible. The only parameter this class expects is the name server's IPv6 address.

The client.conf File

The client.conf file contains each client's data; Listing 2 provides an example with only one client. The identifier is in the square brackets. Dhcpy6d uses the hostname for the entry in DNS. The MAC address is used to identify the client; you can also specify multiple addresses.

Listing 2: client.conf

01 [testclient]
02 hostname = v6client
03 mac = 02:01:02:03:04:09
04 address = 2001:db8::5555
05 class = special

The parameter in line 4 contains an address that the client receives in addition to the address from the template in the address range. Finally, the last line allocates the client to its class. Instead of the MAC, the system administrator may also use one or more DUIDs with the DUID parameter.

After modifying both configuration files for your own setup and with dhcpy6d running on the router, type ifconfig on the client; if the output is similar to Listing 3, you can start to celebrate your success.

Listing 3: ifconfig Shows the IPv6 Assignment

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
      inet6 2001:db8::201:203:409  prefixlen 64  scopeid 0x0<global>
      inet6 2001:db8::5555  prefixlen 64  scopeid 0x0<global>
      inet6 fe80::1:2ff:fe03:409  prefixlen 64  scopeid 0x20<link>
      ether 02:01:02:03:04:09  txqueuelen 1000  (Ethernet)

Test Results and Conclusions

In theory, IPv6 network administrators can manage without a DHCP server; however, in practice, with larger networks (and most IPv6 networks usually are large) the additional parameters transmitted through DHCP are important to the configuration.

Dhcpy6d left a mixed impression. The idea of ignoring the RFC, prompted by practical considerations, and allowing mapping via the MAC address doesn't appear far off the mark at first. After all, the way the DHCPv6 service calculates the DUIDs differs from implementation to implementation anyway. But what I really felt was missing was the ability to assign an address based on the network segment the client is put in. DHCP relay agents are also used with IPv6 in larger networks, and in addition to the MAC address, the DHCPv6 server needs to know which segment the client resides in so the correct parameters are available for the network.

Dhcpy6d relies on individual client definitions and classes. Unknown clients on networks always end up in the default class; they are therefore allocated incorrect addresses and, just as an example, maybe the wrong DNS server. You can only manage this situation by sorting the entries manually.

Henri Wahl, the software's author, provides good support for user questions, and a steady stream of questions helps the developers learn what is or isn't working in the real world. Our test team detected a few logical loopholes using a different approach to the configuration, and our research prompted a number of Git commits.