Exploring dhcpy6d, a DHCP server for IPv6 networks
Not Just Addresses
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:
- A timestamp plus link layer (the MAC address with Ethernet).
- An enterprise ID plus a variable part.
- Just the link layer address.
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).
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:
-
range
, to specify a from-to range. -
id
, to allocate an ID in the client definition. -
random
, to use a random number.
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.