Using DHCPv6-PD on Ubuntu 20.04 with systemd-networkd to route multiple prefixes
- By nygren
- Sat 18 June 2022
Note that this post assumes you already have extensive experience with Linux and IPv6. Most people are much better off using a distribution such as OpenWRT that handles all of this complexity for you. If you want to know why IPv6 matters, check out Akamai's blog post on "10 Years Since World IPv6 Launch".
The systemd-networkd service in Ubuntu 20.04 has enough support for DHCPv6-PD to obtain a prefix from an upstream ISP and subdivide it across local subnets, providing a /64 per subnet. For example, Comcast provides a /60 which has enough space for 16 subnets.
As far as I can tell, the ability to debug what is going on here or obtain state is almost entirely lacking. This makes it very hard to use troubleshoot issues or even tell what is going on.
Because netplan doesn't have enough features to configure DHCPv6-PD yet (see https://bugs.launchpad.net/netplan/+bug/1771886), some of the configuration needs to live in systemd-networkd overrides.
Configuring the Interfaces
I am assuming starting with a netplan configuration like the following:
network: ethernets: eno1: # ISP1 dhcp4: true dhcp6: true accept-ra: true ipv6-privacy: false nameservers: search: [ example.org ] dhcp4-overrides: use-dns: false use-hostname: false use-ntp: false dhcp6-overrides: use-dns: false use-hostname: false use-ntp: false eno2: # LAN dhcp4: false optional: true version: 2 vlans: en-main: id: 6 link: eno2 dhcp4: no addresses: - 10.1.0.0/24 optional: true en-guest: id: 7 link: eno2 dhcp4: no addresses: - 10.2.0.0/24 optional: true
This has interfaces:
- eno1 = WAN
- eno2 = Primary LAN
- en-main = Main VLAN
- en-guest = Guest VLAN
While netplan and systemd-networkd somehow collaborate to put this
netplan config into files such as
/run/systemd/network/10-netplan-eno1.network, there is no way to get
the rules needed for enabling DHCPv6-PD into those dynamically
generated files in /run.
Thankfully, you can put overrides in that systemd-networkd will read.
systemd.network(5) man page for more details on all of the options available
for these files.
To configure a DHCPv6-PD client on the WAN interface (eno1 in my case),
[Network] IPv6PrivacyExtensions=no [DHCPv6] ForceDHCPv6PDOtherInformation=yes PrefixDelegationHint=::/56
You can specify a smaller value for PrefixDelegationHint if needed (eg, /60 for Comcast Residential).
For each of the LAN interfaces, create files such as
[Network] IPv6PrefixDelegation=dhcpv6 IPv6DuplicateAddressDetection=1 IPv6PrivacyExtensions=no LinkLocalAddressing=ipv6 [IPv6PrefixDelegation] RouterLifetimeSec=1800
Note that if you want to use both DHCPv6 provided addresses and your own (eg, to mix in ULA) this may be possible by setting IPv6PrefixDelegation=true, but I have not tried this.
You can either reboot, or you can restart systemd-networkd with:
systemctl restart systemd-networkd
Some big caveats I've noticed:
- The IPv6 address on the WAN link (eg, eno1) comes from an RA ND assignment, not a DHCPv6 prefix
- The individual LANs/VLANs don't appear to get IPv6 addresses assigned. I haven't yet figured out how to get on-link addresses. As such,
ip addrwon't show addresses on those links.
Testing and Debugging
As of the systemd-networkd in Ubuntu 20.04 there aren't good ways to tell what is going on.
networkctl status provides either no information or misleading information.
Some things that may be helpful:
ip -6 route listwill list the prefixes assigned to the interfaces
rdisc6 en-guestwill do router discovery on that interface (eg, en-guest in this case) and will show the assigned prefix
- Doing a
tcpdump -s 1500 -vvv -i eno1 port 546 or port 547and then a
systemctl restart systemd-networkdwill show the DHCPv6-PD lease including prefix length received from the WAN ISP
journalctl -xeu systemd-networkdwill give some logging information from systemd-networkd but I have yet to figure out how to get the most relevant parts logged.
More network logging
systemctl edit systemd-networkd to add in:
And restart systemd-networkd service and looking at logs:
systemctl restart systemd-networkd journalctl -b -u systemd-networkd
Shows a little more info, but still not some of the things that I'd hope to see from looking at the systemd-networkd code.
I'll update this when I upgrade to Ubuntu 22.04 as hopefully it has some more features. If you have any suggestions for better ways of doing things above, they are welcome. I'm unfortunately unable to provide tech support for anything in the above, however...