How to Configure DHCPv6 Prefix Delegation in Ubuntu Using systemd-networkd

In modern IPv6 networking, internet service providers (ISPs) and enterprise upstream routers allocate IPv6 address space to edge gateways using DHCPv6 Prefix Delegation (DHCPv6-PD, RFC 8415). Instead of assigning a single IPv6 address, the upstream provider delegates a routed address block — typically a /56 or /64 prefix — to the customer premises equipment (CPE) or border server. The gateway machine must then divide this delegated pool into individual /64 subnets, assign them across internal LAN interfaces or VLAN bridges, and broadcast IPv6 Router Advertisements (RA) to downstream clients.

On Ubuntu Server, this entire prefix delegation, subnet splitting, and router advertisement pipeline can be configured natively through systemd-networkd without installing external daemons such as radvd, dhcp6c, or dibbler. By declaring prefix delegation directives within network files in /etc/systemd/network/, network administrators can build resilient, zero-maintenance IPv6 routing gateways.

Understanding DHCPv6 Prefix Delegation Architecture in systemd-networkd

When operating an Ubuntu machine as a multi-homed IPv6 router, systemd-networkd manages prefix delegation across two primary roles:

  • Upstream WAN Interface (DHCPv6 Client): Requests and leases an IPv6 delegated prefix from the ISP’s DHCPv6 server using the [DHCPv6] section. The requested prefix length is specified using PrefixDelegationHint=.
  • Downstream LAN/VLAN Interfaces (DHCPv6-PD Server & RA Broadcaster): Receives sliced sub-prefixes via [DHCPv6PrefixDelegation] stanzas, generates unique local interface addresses, and announces the prefixes to local devices via the internal IPv6 Router Advertisement engine ([IPv6SendRA]).

For example, if your upstream ISP delegates a 2001:db8:1234:5600::/56 block, systemd-networkd automatically slices it into distinct /64 subnets (e.g. ...:5601::/64 for corporate LAN, ...:5602::/64 for guest Wi-Fi, and ...:5603::/64 for IoT VLANs) based on configured subnet IDs.

Enabling IPv6 Packet Forwarding on Ubuntu

Before configuring systemd-networkd to route IPv6 traffic, verify that kernel IPv6 packet forwarding is enabled system-wide. Open or create /etc/sysctl.d/99-ipv6-forwarding.conf:

sudo nano /etc/sysctl.d/99-ipv6-forwarding.conf

Insert the following sysctl parameters:

net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1

Apply the sysctl parameters immediately without rebooting:

sudo sysctl --system

Confirm the kernel accepts forwarded IPv6 datagrams:

sysctl net.ipv6.conf.all.forwarding

Configuring the Upstream WAN Interface for Prefix Delegation

Assume the upstream physical interface connected to the ISP modem or optical ONT is named enp1s0. Create or edit /etc/systemd/network/10-wan.network:

sudo nano /etc/systemd/network/10-wan.network

Populate the file with the WAN configuration:

[Match]
Name=enp1s0

[Network]
Description=Upstream WAN Gateway with DHCPv6-PD
DHCP=ipv6
LinkLocalAddressing=ipv6
IPv6AcceptRA=yes

[IPv6AcceptRA]
UseDNS=yes

[DHCPv6]
WithoutRA=solicit
PrefixDelegationHint=::/56
UseDNS=yes
UseNTP=yes

Configuration details explained:

  • DHCP=ipv6: Configures the interface to run a DHCPv6 client.
  • IPv6AcceptRA=yes: Accepts default IPv6 routes and router flags advertised by the upstream gateway.
  • PrefixDelegationHint=::/56: Explicitly hints to the ISP’s DHCPv6 server that this router requests a /56 delegated prefix block.
  • WithoutRA=solicit: Ensures the DHCPv6 client initiates a solicit exchange even if the upstream router advertisement omits the managed (M) or other configuration (O) flags.

Configuring Downstream LAN Interfaces to Consume Delegated Prefixes

Now configure the internal network interfaces that will distribute the delegated subnets to client computers and mobile devices. In this architecture, assume the internal corporate network is connected to enp2s0, and an internal server network is connected to enp3s0.

Create the network configuration file for enp2s0 (/etc/systemd/network/20-lan.network):

sudo nano /etc/systemd/network/20-lan.network

Insert the following configuration:

[Match]
Name=enp2s0

[Network]
Description=Internal Corporate LAN
LinkLocalAddressing=ipv6
IPv6SendRA=yes
DHCPv6PrefixDelegation=yes

[DHCPv6PrefixDelegation]
SubnetId=0x1
Announce=yes

[IPv6SendRA]
Managed=no
OtherInformation=no
RouterLifetimeSec=1800
EmitDNS=yes
DNS=2606:4700:4700::1111

Create the configuration for the secondary downstream interface enp3s0 (/etc/systemd/network/21-servers.network):

sudo nano /etc/systemd/network/21-servers.network
[Match]
Name=enp3s0

[Network]
Description=Internal Server Subnet
LinkLocalAddressing=ipv6
IPv6SendRA=yes
DHCPv6PrefixDelegation=yes

[DHCPv6PrefixDelegation]
SubnetId=0x2
Announce=yes

[IPv6SendRA]
RouterLifetimeSec=1800

Key parameters explained:

  • DHCPv6PrefixDelegation=yes: Instructs systemd-networkd to automatically bind a portion of the prefix acquired on the WAN interface to this link.
  • SubnetId=0x1 and 0x2: Specifies the hexadecimal offset applied to the delegated base prefix, guaranteeing that each downstream interface receives a non-overlapping, unique /64 subnet.
  • IPv6SendRA=yes: Enables the internal Router Advertisement daemon, allowing client endpoints on the LAN to auto-configure their own IPv6 addresses using SLAAC (Stateless Address Autoconfiguration).

Applying Configuration and Validating IPv6 Prefix Allocation

Restart systemd-networkd to apply the configuration and initiate the upstream prefix negotiation:

sudo systemctl restart systemd-networkd

Check the status of the WAN interface using networkctl:

networkctl status enp1s0

Look for the DHCPv6 Client status block. The output will show the assigned prefix (e.g. Prefix: 2001:db8:abcd:1200::/56) and lease expiration timers.

Inspect the downstream LAN interface:

networkctl status enp2s0

The output will confirm that systemd-networkd has generated an interface IP within the delegated subnet (e.g. 2001:db8:abcd:1201::1/64) and is actively transmitting Router Advertisements.

Verify that kernel routes are installed properly:

ip -6 route show

From a client machine connected to the downstream LAN, confirm that SLAAC has assigned an address and test end-to-end global connectivity:

ping -6 -c 4 cloudflare.com

Troubleshooting Common Prefix Delegation Issues

If downstream interfaces do not acquire prefixes or clients lose IPv6 connectivity, evaluate these common causes:

  • Firewall Filtering DHCPv6 Packets: Ensure ufw or nftables on the Ubuntu router does not block incoming UDP port 546 on the WAN interface:
    sudo ufw allow in on enp1s0 proto udp to any port 546 comment "DHCPv6 Client Ingress"
  • Inconsistent DUID (DHCP Unique Identifier): Some cable and fibre ISPs bind delegated prefixes strictly to the client DUID. If the DUID changes on reboot, the ISP rejects the request. Enforce a static DUID in /etc/systemd/networkd.conf:
    [DHCPv6]
    DUIDType=vendor
  • Missing Default IPv6 Route: If the WAN interface receives a delegated prefix but cannot route packets externally, verify that the ISP’s router advertisements are not being ignored by checking sysctl net.ipv6.conf.enp1s0.accept_ra (which must be set to 2 when forwarding is enabled system-wide).

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.