Setting up IPv6 using a DHCP client
Our ISP (internet service provider) finally started offering IPv6. On the server, I received static configuration. Here, they are using DHCP6 with prefix delegation and it isn’t as straightforward as one would expect.
There are probably three most commonly used DHCPv6 clients for Linux – dhcpcd, dibbler and WIDE-DHCPv6. Although I compiled WIDE-DHCPv6 by fixing some compilation issues, I decided not to use it just because it is not actively maintained. So first I tried dhcpcd and immediately faced a problem.
Please note that I am describing IPv6-only configurations here. Of course you can extend them to ipv4 by reading the manual(s).
Also note that enp0s1 is the external facing interface (the one which connects to the ISP) and br0 is my internal bridge with LAN and WLAN interface for my local clients.
dhcpcd
Yes, dhcpcd supports DHCPv6. It is not very well documented with working examples, though. You can make a configuration like this:
# Inform the DHCP server of our hostname for DDNS. hostname # Rapid commit support. # Safe to enable by default because it requires the equivalent option set # on the server to actually work. option rapid_commit # options to request from the DHCP option domain_name_servers, interface_mtu # A ServerID is required by RFC2131. require dhcp_server_identifier # only configure ipv6 ipv6only # disable routing solicitation noipv6rs # don't touch these interfaces at all denyinterfaces wlp2s0 enp1s0 interface enp5s0 # enable routing solicitation get the default IPv6 route ipv6rs # request a normal (IA_NA) IPv6 address with IAID 1 ia_na 1
That config will make dhcpcd obtain one IPv6 address /128 via interface enp5s0 and set the address to that interface.
If you are the only user it will work for you and no more steps needed.
The more complicated situation happens, if you are doing it on the router and want to request prefix delegation and assign IPv6 addresses from the delegated prefix to more clients on our LAN.
Normally you would do something like this (editing interface block only):
interface enp5s0 # enable routing solicitation get the default IPv6 route ipv6rs # request a normal (IA_NA) IPv6 address with IAID 1 ia_na 1 # request prefix delegation (IA_PD) and make routes from br0, # also sets first IP from the prefix to that interface # IAID is 2 ia_pd 2 br0/0
The problem is, my ISP won’t give me prefix delegation for IAID of 2 for some unknown reason. DHCP server is responding “Sorry, no prefixes could be allocated at this time”. Setting IAID to 1 for both ia_na and ia_pd is prohibited by RFC so dhcpcd complains with “option type mismatch” and sets IAID of first 4 bytes of br0 MAC for IA_PD and the same problem occurs.
The solution is, surprisingly, to set IA_NA IAID to 0 and IA_PD IAID to 1. This was not mentioned anywhere and manuals always showed IAIDs of 1. So the correct setting for dhdpcd for me would be:
interface enp5s0 # enable routing solicitation get the default IPv6 route ipv6rs # request a normal (IA_NA) IPv6 address with IAID 0 ia_na 0 # request prefix delegation (IA_PD) and make routes from br0, # also sets first IP from the prefix to that interface # IAID is 1 ia_pd 1 br0/0
dibbler-client
Alternatively you can use Dibbler. Its configuration with prefix delegation looks like this:
# run this script hook on every event script "/etc/dibbler/client-notify.sh" # Uncomment following line to skip confirm sending (after crash or power outage) skip-confirm # How much/where to log log-mode syslog # 7 = omit debug messages, 8 with debug log-level 7 # split received prefix from upstream router into the following interfaces downlink-prefix-ifaces br0 # interface to the ISP iface "enp5s0" { # Quick configuration with two messages only (if server supports it) rapid-commit 1 # Request a regular (non-temporary) address (IAID 1 by default if not spec.) ia # Request prefix delegation (IAID 1 by default if not specified) pd # options to request option dns-server }
The hook script just sets the first IP from the delegated prefix to the downlink interface (in by case br0 but the script is universal – no need to edit it):
/etc/dibbler/client-notify.sh
#!/bin/bash # for each downlink interface... ifn=0 for iface in $DOWNLINK_PREFIX_IFACES; do ifn=$(( $ifn + 1 )) prefix=`printenv PREFIX$ifn` prefixlen=`printenv PREFIX${ifn}LEN` # remove all global ipv6 addresses on the iface ip -6 addr flush dev $iface scope global if [ "$1" == "add" -o "$1" == "update" ]; then # set the first IP from the prefix ip addr add "${prefix}1/${prefixlen}" dev $iface fi done
Of course, don’t forget to make the script executable:
chmod +x /etc/dibbler/client-notify.sh
radvd
To allow autoconfiguration for clients on br0, you need to run radvd as well.
Regardless of your DHCP client.
The configuration of radvd can look like this:
interface br0 # LAN interface { AdvManagedFlag off; # no DHCPv6 server here. AdvOtherConfigFlag off; # not even for options. AdvSendAdvert on; AdvDefaultPreference high; AdvLinkMTU 1500; prefix ::/64 #pick one non-link-local prefix assigned to the interface and start advertising it { AdvOnLink on; AdvAutonomous on; }; };
Remaining issues
Also ensure your firewall allows router advertisements from your ISP. You may consider disabling the firewall temporarily during testing.
Next, if your device acts as a router and has forwarding enabled, make sure to set accept_ra for the external interface to 2:
sysctl sysctl net.ipv6.conf.enp5s0.accept_ra=2
I hope my day lost by configuration, trials and errors helped you setting up your DHCP client correctly sooner. :)
Your info re: iaid on dhcpcd when using the box as a router was invaluable. The official manpage had me down a dead end. I’m also looking to do the dhcpcd route in the future as wide has (sadly) stagnated/died. I still have some more tweaks and things to test – but I think I’m in business now.
Thanks so much for this write-up.
Thanks a LOT, especially for the sysctl sysctl net.ipv6.conf.enp5s0.accept_ra=2 part!
Hi! Author of dhcpcd here. Just feeding back on your query qbout IAID usage in the manual.
Taken from the man page:
iaid iaid
Set the Interface Association Identifier to iaid. This option
must be used in an interface block. This defaults to the VLANID
(prefixed with 0xff) for the interface if set, otherwise the last
4 bytes of the hardware address assigned to the interface. Each
instance of this should be unique within the scope of the client
and dhcpcd warns if a conflict is detected. If there is a
conflict, it is only a problem if the conflicted IAIDs are used
on the same network.
This is what dhcpcd is warning about. IAID uniqueness within the scope of a DHCPv6 message is an RFC requirement. What this means is that IA_NA and IA_PD should have different IAIDs, the actual value is opaque so your upstream DHCP server shouldn’t blindly reject an IAID of 2.
@Roy Marples
Thanks for additional information – appreciated! My ISP appears to be using ISC Kea DHCP server. Maybe they have it configured wrongly but it’s hard to discuss technical issues with them. I am actually surprised they finally provide IPv6 (and they apparently don’t know how to limit speed over IPv6 so the speeds are few times faster than over IPv4 :P). I edited the article to reflect your comment. Thanks for developing famous dhcpcd and others (I still use OpenRC on some machines)!!
[…] https://k3a.me/setting-up-ipv6-using-a-dhcp-client/ […]