DHCPv6 Prefix Delegation for IPv6

Updated: Jul 8, 2018

I recently switched ISP and gained native IPv6 connectivity. Googled for instructions to setup IPv6 on my ER-X. None of the articles and forum discussions that I found helped me complete the mission successfully. DHCPv6-PD is commonly used by ISPs to dispatch IPv6 addresses to users. Here I share my findings. The details are for Edgerouter's but the concepts apply to any Linux routers. Below assume eth0 as WAN switch0 as LAN.

Configure DHCPv6-PD

01 $ configure
02 edit interfaces ethernet eth0
03 set dhcpv6-pd rapid-commit enable
04 set dhcpv6-pd no-dns
05 set dhcpv6-pd pd 0 prefix-length 56
06 set dhcpv6-pd pd 0 interface switch0  service slaac
07 set dhcpv6-pd pd 0 interface switch0 prefix-id 0
08 set dhcpv6-pd pd 0 interface switch0 host-address ::1
09 set ipv6 address autoconf

Line 3-8 sets up dhcpv6-dp for WAN eth0 and LAN switch0. DHCPv6-PD exchanges four messages between client and server. rapid-commit reduces to two messages. However, not all ISPs support it. no-dns tells the LAN interface not to advertise name servers received from ISPs. It's essential for people who run a name server for their LAN. For my ISP, name servers are always passed to me during DHCPv6-PD handshake. Under the hood, 'no-dns' prevents RDDNS lines from being generated in /etc/radvd.conf for RADVD.

Check prefix-length with your ISP. 56 is a common prefix length. Other possible values are 48 and 64 but both are rare as /48 gives out an outrageous number of subnets and /64 gives out only one subnet.

Line 6 setup LAN clients to use SLAAC for forming IPv6 host addresses.

prefix-id is a n-bit integer that represents one subnet. n equals to 64 minus prefix-length. With prefix-length 56, I get 2^8=256 subnets. Line 7 is redundant here as default is 0. For multiple subnets, Lines 5-8 are repeated for each subnet with a unique PD number and unique prefix-id.

host-address tells interface switch0 to use the provided suffix in forming the IPv6 address. If not specified, a modified form of MAC address of switch0 will be used.

Line 9 tells interface eth0 to use SLACC to form its IPv6 host address. Without it, no public IPv6 address will be configured.

DHCPv6 servers may handle both IA_NA and IA_PD requests. Some ISPs only work with IA_PD. To configure that add set dhcpv6-pd prefix-only. Note that some ISPs like mine will not work at all if prefix-only is specified.

Configure Additional IPv6 Firewall

set firewall ipv6-name WAN_LOCAL-v6 rule 35 action accept
set firewall ipv6-name WAN_LOCAL-v6 rule 35 destination port 546
set firewall ipv6-name WAN_LOCAL-v6 rule 35 protocol udp        
set firewall ipv6-name WAN_LOCAL-v6 rule 35 description 'DHCPv6 reply'
set firewall ipv6-name WAN_LOCAL-v6 rule 40 action accept
set firewall ipv6-name WAN_LOCAL-v6 rule 40 protocol ipv6-icmp
set firewall ipv6-name WAN_LOCAL-v6 rule 40 description ipv6-icmp
set firewall ipv6-name WAN_IN-v6 rule 40 action accept
set firewall ipv6-name WAN_IN-v6 rule 40 protocol ipv6-icmp
set firewall ipv6-name WAN_IN-v6 rule 40 description ipv6-icmp

DHCPv6 servers listen on UDP/547 and clients listen on UDP/546. Your router is a client. Incoming UDP traffic on port 546 should be accepted. IPv6-ICMP is also critical to IPv6 operations. Or else you get very weird behaviour. A lesson I learned after spending hours debugging and exchanging a few calls with my ISP's clueless support.

Not accepting IPv6-ICMP on local router didn't get me a public IPv6 address on the WAN interface. More fatal is missing the default IPv6 route to the remote gateway! Even though prefix and host address successfully created on the LAN interface. Router Advertisements also work as expected but all LAN clients were unable to talk to the outside world over IPv6.

Bug on no-dns

The result of DHCPv6-PD configuration will look something like this:

dhcpv6-pd {
    no-dns # no effect sometimes
    pd 0 {
        interface switch0 {
            host-address ::1
            no-dns # no CLI support but add manually and effective always
            prefix-id 0
            service slaac
        prefix-length 56
    rapid-commit enable

The comments are added here to be descriptive. The CLI adds the first no-dns which does not consistently exclude ISP name servers in /etc/radvd.conf. So I decided to manually edit /config/config.boot to include the second no-dns. With no-dns inside the LAN block, EdgeOS always produces the correct radvd.conf. This bug is valid as of EdgeOS v1.9.1.1.

Update: 10/6/17. There is CLI to insert the 2nd no-dns. The question is why do we need two 'no-dns'. What each means and intends to function?

Update: 7/8/18. Turns out the outer no-dns for the WAN interface instructions Ubiquiti's config daemon not to write name servers from DHCP server to /etc/resolv.conf. The inner no-dns for the LAN interface prevents RA daemon from passing nameservers from DHCP server to LAN clients. You'll need to specify both if you don't want ISP nameservers to interfere your own DNS server.

Useful Debug Commands

To force DHCPv6-PD renewal

01 release dhcpv6-pd interface eth0
02 delete dhcpv6-pd duid
03 renew dhcpv6-pd interface eth0

Line 1 kills dhcp6c process. Line 3 starts it. Usually last line alone is sufficient for renewal.

To run DHCPv6-PD client in verbose mode with logging

sudo /usr/sbin/dhcp6c -dDf -c /var/run/dhcp6c-eth0-pd.conf -p /var/run/dhcp6c-eth0-pd.pid eth0 2> /var/tmp/dhcp6c.log

You've to kill dhcp6c first.

Hopefully this post saves people from the pitfalls that I had to go through. Please let me know in case it helps you.

comments powered by Disqus