Internode IPv6 on Linux with systemd-networkd

Internode’s instructions for configuring IPv6 routing on linux are pretty terse, merely giving some suggestions for using WIDE DHCPv6 and radvd. On modern Linux with systemd, these extra daemons are unnecessary; all that’s required is systemd-networkd. This post describes the problems and how I got dual-stack IPv4/IPv6 routing over Internode’s NBN service, using a Raspberry Pi running Debian Buster.

Firstly, here’s all the things we want the router to do:

  • Create a PPPoE connection to Internode via the NBN (HFC).
  • Establish the IPv6 address of the upstream router and create a default route there.
  • Issue Router Advertisements (RA) to other hosts on the LAN so that they can configure their global IPv6 address and default route using SLAAC.
  • Act as a DHCPv6 client for Prefix Delegation. It’s not obvious why this is required: Internode allocates a static /56 prefix, and I can statically configure my router to advertise that in its RA. However, it turns out that without the DHCP lease, upstream routes aren’t created for hosts in the /56 prefix!

Glen Turner has an excellent guide for a setup on Debian Wheezy consistent with Internode’s recommendation, using the radvd and wide-dhcpv6-client packages. But on Debian Buster, this feels quite outdated: wide-dhcp6cd will exit immediately (rather than wait) if its config mentions an interface that doesn’t exist. Hence systemd disables it because of the fail-loop it enters on system boot when ppp0 doesn’t exist. On top of this, there’s no good logging level for wide-dhcp6cd; the “debug” level pours out minutiae of config-file parsing, while the merely “verbose” level gives no indication about what the DHCP replies contain. It’s also using a SysV-style init script rather than a modern systemd service.

I’ve also avoided using GNOME’s NetworkManager, which I feel is too bloated for a headless router in a stable network topology.

My configs follow.

Continue reading “Internode IPv6 on Linux with systemd-networkd”