Feb 152011

Amongst playing with the YubiKey, I also had a look at DHCPv6.  As people well know, IPv4’s days are numbered, and given we’re all going to have to jump across to IPv6 fairly soon, I figured I had better get acquainted with the newer protocols that come with it.

I’ve had my network running dual-stack for some time now.  This has been achieved using stateless autoconfiguration and router advertisments, which work fairly well.  Today though I decided I’d give DHCPv6 a crack.  For this, you will need the latest ISC dhcp package, net-misc/dhcp-4.1.0, which is hard-masked.

I hope to get something more mature going, but here are some notes who may wish to try this at home.

Setting up DHCPv6

Start by installing the net-misc/dhcp-4.1.0, on both server and clients…you will need to unmask it first:

# echo =net-misc/dhcp-4.1.0 | tee -a /etc/portage/package.unmask >> /etc/portage/package.keywords
# emerge -a dhcp

The -4 and -6 flags

Now, that will install the DHCP server and client.  The catch that initially caught me is that ISC dhcpd cannot run on IPv6 and IPv4 simultaneously. Neither can the client, but we’ll get to that.  Both server and client are put into IPv4 mode by running with -4 in the options, or -6 for IPv6 mode.  Documentation says it defaults to IPv6 mode, but my experience has been the opposite (maybe a Gentoo patch does this).

Server set-up

Needless to say, if you’ve got your network running IPv4, at most you might have to edit /etc/conf.d/dhcpd to add -4 to the start-up options (DHCPD_OPTS to be exact).  Easy.  It’ll work as before. If you want IPv6, okay, make that -6 in DHCPD_OPTS, no sweat. But what if you want both? Ohh fun, we need a second dhcpd instance.

My solution; copy each /etc/init.d/dhcpd and /etc/conf.d/dhcpd to /etc/init.d/dhcpd-v6 and /etc/conf.d/dhcpd-v6 respectively.  Make the necessary changes to /etc/init.d/dhcpd-v6 and /etc/conf.d/dhcpd-v6.  So that the two don’t clash, I thought it wise to substitute DHCPD with DHCPDV6 using a text-editor (replace all).

You’ll also want to rename the leases file (dhcpd.leases, I chose dhcpd-v6.leases) and the PID file.  In addition the init script calls dhcpd to check the configuration in checkconfig(), so add -6 there too.  To save you going back and adding it in /etc/conf.d/dhcpd-v6, you can also add the -6 flag to the start-stop-daemon call in in start().  Do similar manipulations to /etc/conf.d/dhcpd-v6.

As for the server configuration file itself, I called my IPv6 config file /etc/dhcp/dhcpd-v6.conf to differentiate it from v4.  The two will need separate configuration files.  At the top of the v6 configuration file, you’ll want to point it to new PID and leases files:

pid-file-name "/var/run/dhcp/dhcpd-v6.pid";
lease-file-name "/var/lib/dhcp/dhcpd-v6.leases";

Adding that to the top of dhcpd-v6.conf will take care of this.  If you’ve done everything right, you should be able to start the DHCPv6 daemon, and add it to your runlevels as per normal.  DHCPv6 listens on port 547/UDP — look for it in netstat.

Client set-up

Client set-up isn’t too difficult, the fun bit is integrating dhclient into the init scripts.  OpenRC knows how to drive dhclient in v4-mode, but not v6.  It too, cannot run in both v4 and v6 mode simultaneously.  The solution: a new net module.  Copy /lib/rc/net/dhclient.sh to /lib/rc/net/dhclientv6.sh.

Rename all the functions changing dhclient to dhclientv6 (don’t use replace-all this time), and change the “provide” line in dhclientv6_depend to dhcpv6.  In dhcpclientv6_expose, do likewise, rename the variables dhclientv6 and dhcpv6.  Finally,  in each  call to the dhclient binary itself, add -6 to it to put it in IPv6 mode, and rename the PID file to add -v6 to the file name.

Save the new file.  Now in /etc/conf.d/net, use the following:

config_eth0=( "dhcp" "dhcpv6" )

Things that I have not yet figured out

Dynamic DNS

This is one of the reasons why I wanted DHCPv6 in the first place.  Remembering IPv4 addresses is bad enough.  IPv6 is a pain.  I have more success citing Pi than remembering the IPv6 address of all my computers.  The statically assigned ones aren’t too bad since the prefixes are all the same, it’s the autoconfigured ones that are a nuisance.

It should be doable, but I haven’t yet worked out how to make dhcp update the nameserver with AAAA records.  This is still in its infancy though.  Lots of rough edges.  I note dhclient doesn’t seem to be passing on the hostname of the computer, which could be part of the problem.

Address pools and class-based assignment

Address pools are handy things.  In ISC dhcpd, I can classify each of the computers I have by their MAC address and assign each class an address pool.  Or at least I could when it’s in IPv4 mode.

I have a nice set-up on IPv4 where if the DHCP server knows the MAC address, it’ll put that computer on the right subnet.  We have three IPv4 subnets here; one for my computers, one for my father’s and a “de-militarised zone” where any foreign computers get put (along with the web server, well actually it exists on all three).  Below is an example:

subnet netmask {
  pool {
    range dynamic-bootp;
    allow members of "stuartslan";

  ddns-domainname "redhatters.yi.org.";
  ddns-rev-domainname "in-addr.arpa.";
  ddns-updates on;
  update-conflict-detection off;
  allow client-updates;

  /* ... */
/* ... */
subclass "stuartslan" 1:6c:f0:49:ef:84:7c; # beast eth0
subclass "stuartslan" 1:6c:f0:49:ef:84:7e; # beast eth1
subclass "stuartslan" 1:08:00:27:ab:7c:b9; # Win2K VirtualBox
subclass "stuartslan" 1:08:00:27:27:bf:55; # uClibc VirtualBox
subclass "stuartslan" 1:00:08:0d:5c:08:51; # Laptop "vk4mslp2" ethernet
subclass "stuartslan" 1:00:12:f0:bd:de:06; # Laptop "vk4mslp2" wireless
/* ... */

I haven’t figured out how to replicate this in DHCPv6.  The following does not work:

subnet6 2001:388:d000:1153::/64 {
  pool {
    allow members of "stuartslan";
    range6 2001:388:d000:1153::1000 2001:388:d000:1153::ffff:ffff;

  ddns-domainname "redhatters.yi.org.";
  ddns-rev-domainname "ip6.arpa.";
  ddns-updates on;
  allow client-updates;
  /* ... */

I plan to keep researching these things, and I’ll see what I can do about getting the updates into Gentoo’s init scripts so that DHCPv6 is handled.  A lot of what I did today were quick hacks that will likely make people shudder, but it’s working for now, we’ll see how it goes.

  4 Responses to “Gentoo and DHCPv6”

  1. http://bugs.gentoo.org/show_bug.cgi?id=353420
    I’ve put there a pair of updated versions, the masked version is a security risk

  2. also ISC dhcp for IPv6 is the red-hat dhcpv6 merged maybe http://tldp.org/HOWTO/Linux+IPv6-HOWTO/hints-daemons-dhcpv6..html can work but I still need to find time to play with it

  3. Instead of copying the init script, you might be better off symlinking it instead. That is, have /etc/init.d/dhcpd-v6 -> /etc/init.d/dhcpd.

    Gentoo is clever enough to source the conf.d scipt with the same name as the init script. This way you won’t accidentally lose your v6 daemon if you upgrade the dhcp package which changes the init script in some non-backward compatible way.

  4. On the patches, I’ll have a look. I trust my network’s users for the most part though, and I don’t run dhcpd on the public internet, so while the security threat is of concern, it’s not a big issue on this network.

    As for symlinking, the problem is that the dhcpd daemon needs to be called with the “-6” parameter to be put in IPv6 mode. Now there are provisions to do this when starting the daemon, granted. However, the init script also calls dhcpd to check the configuration file, which similarly must be checked in the right mode otherwise dhcpd will claim numerous statements aren’t valid in IPv4 mode.