In mid-December 2013, TekSavvy adopted DHCPv6-PD instead of static route configurations. DHCPv6-PD makes it easier for users with household routers to configure IPv6: most recent routers support it out of the box, so enabling IPv6 is just two clicks away.

This article focuses on the Debian GNU/Linux operating system or for more custom types of setups.

OpenWRT

Short version: If you are using an OpenWRT-based router, this article will not help you. Recent versions of OpenWRT have very good IPv6 support.

If you have trouble debugging OpenWRT, these old instructions from the support forum may help.

What is DHCPv6-PD?

The “PD” in “DHCPv6-PD” stands for “prefix delegation”. This means that the DHCPv6 server is not distributing a single IP address, but rather a prefix (subnet) of addresses. In turn, the DHCPv6 client will assign one of those subnets to the local area network. Most providers allocate a /56 address block. This makes it possible to create 256 sub-networks at home, each with millions of devices. One network is typically a /64, so you can assign one of those /64 (out of 256) to your wifi, for example. While having 256 home network segments may sound excessive, IPv6 is there to hopefully be useful for the next 20 years. Even a typical geek might use today about a dozen network segments.

If you are using a full system as a router, such as a standard Debian GNU/Linux or Ubuntu system, the instructions below should help to setup DHCPv6-PD. It assumes you understand the basics of IPv6.

Basic IPv6 PPPoE connection

I have a PPPoE standard configuration, but added the following to my /etc/pppoe/peers/teksavvy :

+ipv6

Connecting PPPoE (sudo pon teksavvy) will show the following equivalent in the system logs:

peer from calling number AC:81:12:00:00:00 authorized
local  LL address fe80::ec91:bb29:123:123
remote LL address fe80::0090:1a00:321:321
local  IP address 206.248.123.123
remote IP address 206.248.321.321

Seen above, IPv6 can use link-local addresses (fe80) for routing, which is kind of neat, i.e. routers don’t need actual global addresses. However, it also means that we do not have any routes configured by default, nor any global IPs configured on our home router.

For example, ppp0 will show something equivalent to:

ppp0      Link encap:Point-to-Point Protocol  
          inet addr:206.248.123.123  P-t-P:206.248.321.321  Mask:255.255.255.255
          inet6 addr: fe80::984c:fe4b🔡123/10 Scope:Link

In the above, we received a public IPv4 address, but not a public IPv6 address. The link-local address (fe80) is only used to speak with other peers on the same physical link (ex: the remote PPP endpoint). There will not be a default route either (ip -6 route).

TekSavvy uses route announcements (RA) so that the home router configures the default route as well as a /64 prefix for auto-configuration. We don’t need the /64, but it can be useful for the default route.

For PPP on a router, this is disabled by default.

To enable the default route from route advertisements:

# sysctl -w net.ipv6.conf.ppp0.accept_ra=2

To auto-configure an IP address to ppp0:

# sysctl -w net.ipv6.conf.ppp0.autoconf=1

After a few seconds, “ifconfig ppp0” should show a global IPv6 address, and “ip -6 route” will show a default route. You should also be able to “ping6 google.com” or he.net from your router.

IMPORTANT: to make sysctl configurations permanent, you can try to add them to /etc/sysctl.conf, or to /etc/ppp/ipv6-up.d/my-network (script executed when the ppp connection is enabled).

Configuring the /56 prefix with DHCPv6-PD

A /64 network prefix is recommend for a single network. However, most IPv6 home topologies need more than one network. For example, the wireless access point (AP) should use its own network (bye bye network bridging), the wired network another network, another for home servers, appliances, etc.

nb: this howto initially recommended WIDE, but it caused me too many problems. I switched to “dhcpcd5” instead.

Install the ‘dhcpcd5’ client:

# apt-get install dhcpcd5

IMPORTANT: if you are using Debian Jessie, use the dhcpcd5 package from ’testing’ instead. The package in Jessie is too old and will cause problems.

The Debian configuration wizard may ask for which interface to listen on: ppp0.

Sample configuration in /etc/dhcpcd.conf:

# A sample configuration for dhcpcd.
# See dhcpcd.conf(5) for details.

# Inform the DHCP server of our hostname for DDNS.
# nb: unfortunately I doubt my ISP supports this.
hostname myroutername.example.org

# only ask for dhcpcd on a specific interface
allowinterfaces ppp0

interface ppp0
    ipv6only
    ia_pd 1 eth1/5

# Use the hardware address of the interface for the Client ID.
#clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
duid

# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit

# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes

# Most distributions have NTP support.
option ntp_servers

# Respect the network MTU.
# Some interface drivers reset when changing the MTU so disabled by default.
option interface_mtu

# Generate Stable Private IPv6 Addresses instead of hardware based ones
slaac private

# A ServerID is required by RFC2131.
require dhcp_server_identifier

# A hook script is provided to lookup the hostname if not set by the DHCP
# server, but it should not be run by default.
nohook lookup-hostname

Since I use Debian Jessie, which has an old version of systemd and limited networkd support, I created a unit file for my specific needs:

vim /etc/systemd/system dhcpcd.service
[Unit]
Description=dhcpcd
After=network.target

[Service]
Type=forking
PIDFile=/var/run/dhcpcd-ppp0-6.pid
Environment=PATH=/sbin:/bin:/usr/sbin:/usr/bin
ExecStart=/sbin/dhcpcd5 -6 --noipv4ll --quiet -t 0 ppp0
ExecStop=/sbin/dhcpcd5 -6 -x ppp0
Restart=always
RestartSec=30
StandardOutput=syslog

[Install]
WantedBy=multi-user.target
Alias=dhcpcd5.service

NB: I also use the “-C” flag of dhcpcd5 to avoid it writing in my /etc/resolv.conf. I manage my own DNS caching servers.

Then enable and start it:

# systemctl enable dhcpcd
# systemctl start dhcpcd

I’m not really familiar with systemd. The above “works for me”. If there are better ways of doing this, please let me know.

Configure radvd for auto-configuration on the networks

Each network with clients (desktops/workstations/laptops) will need radvd so that the clients can auto-configure themselves.

Install radvd:

# apt-get install radvd

Example configuration for a subnet, in /etc/radvd.conf :

interface eth1
{
  AdvSendAdvert on;
  MaxRtrAdvInterval 30;

  prefix ::/64
  {
    AdvOnLink on;
    AdvAutonomous on;
    AdvRouterAddr off;
    AdvValidLifetime 300;
    AdvPreferredLifetime 120;
  };
};

Then restart radvd:

# services radvd restart

Troubleshooting

  • Make sure your firewall is not blocking DHCPv6 communications (worst case: “ip6tables -F” to flush all rules). For the DHCPv6 client, this is UDP port 546 (“ip6tables -A INPUT -i ppp0 -p udp –dport 546 -j ACCEPT”).
  • Check the traffic with tcpdump: “tcpdump -i ppp0 -n -s 4000 -v ip6”

References