When examining IPv6 address assignment in Ubuntu, many administrators notice an interesting behavior: the system receives both a SLAAC-configured address with /64 prefix (from Router Advertisements) and a DHCPv6-assigned address with /128 prefix. This raises valid questions about network design principles.
In your example output:
inet6 2001:xxxx:1f15:yyyy::9/128 scope global
inet6 2001:xxxx:1f15:yyyy:faa9:63ff:fe0c:3ccb/64 scope global dynamic
We see two distinct address assignment mechanisms at work:
- The /64 address comes from SLAAC (Stateless Address Autoconfiguration) using the interface identifier
- The /128 address comes from stateful DHCPv6 assignment
DHCPv6 typically assigns /128 addresses for several important reasons:
- Address Exclusivity: A /128 prefix guarantees no other host will receive this exact address
- Lease Management: DHCP servers need precise control over individual addresses for lease tracking
- RFC Compliance: RFC 8415 doesn't mandate prefix delegation for non-PD cases
Here's a typical ISC DHCPv6 server configuration that would produce this behavior:
subnet6 2001:db8:1f15::/64 {
range6 2001:db8:1f15::100 2001:db8:1f15::200;
prefix6 2001:db8:1f15:: 2001:db8:1f15:: /64;
}
Contrast this with a prefix delegation setup where you might see different behavior:
subnet6 2001:db8:1f15::/64 {
prefix6 2001:db8:1f15:: /64;
allow leasequery;
}
The /128 assignment affects several operational aspects:
- Routing: Hosts need proper RA configurations to ensure routing works correctly
- Firewalling: Security policies must account for both address types
- Monitoring: Network monitoring tools should track both SLAAC and DHCPv6 addresses
To check how your Ubuntu system obtains its IPv6 addresses:
# Check DHCPv6 client process
ps aux | grep dhclient
# View DHCPv6 leases
cat /var/lib/dhcp/dhclient6.leases
# Verify networkd configuration (if using systemd-networkd)
cat /etc/systemd/network/*.network
You might see /64 assignments from DHCPv6 in these scenarios:
- When using prefix delegation (PD)
- With certain enterprise-grade DHCP servers
- When explicitly configured for prefix assignment
When testing IPv6 implementation in Ubuntu, you might notice that while Stateless Address Autoconfiguration (SLAAC) via Router Advertisements (RA) correctly assigns a /64
address, DHCPv6 often assigns an additional IPv6 address with a /128
prefix. Here's a typical interface configuration:
2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether f8:a9:63:0c:3c:cb brd ff:ff:ff:ff:ff:ff
inet6 2001:xxxx:1f15:yyyy::9/128 scope global
valid_lft forever preferred_lft forever
inet6 2001:xxxx:1f15:yyyy:faa9:63ff:fe0c:3ccb/64 scope global dynamic
valid_lft 82162sec preferred_lft 10162sec
inet6 fe80::faa9:63ff:fe0c:3ccb/64 scope link
valid_lft forever preferred_lft forever
The /128
prefix length for DHCPv6-assigned addresses is actually standard behavior per RFC 3315. Unlike IPv4 where DHCP typically provides both address and subnet mask, DHCPv6 assigns individual host addresses with an implicit /128
prefix because:
- IPv6 doesn't use broadcast or ARP, making traditional subnet masks unnecessary
- The address is treated as a standalone endpoint identifier
- Routing information comes separately from Router Advertisements
While the /128
prefix is normal, your DHCPv6 server configuration can influence this behavior. For example, in ISC DHCPv6 server (dhcpd6.conf
), you might see:
subnet6 2001:db8:1f15::/64 {
range6 2001:db8:1f15::100 2001:db8:1f15::200;
# Prefix delegation example (different from address assignment)
prefix6 2001:db8:1f00::/56 2001:db8:1f00::/60;
}
The range6
directive specifies individual host addresses that will be assigned with /128
prefixes, while prefix6
is used for prefix delegation (typically /56
or /60
for downstream networks).
This behavior has several practical consequences:
- Address Scope: The
/128
address is globally routable but treated as a single host - Duplicate Address Detection: Still occurs for DHCPv6-assigned addresses despite the
/128
prefix - Firewall Rules: You'll need to account for both SLAAC (
/64
) and DHCPv6 (/128
) addresses in your rules
Here's an example nftables
rule that handles both address types:
table ip6 filter {
chain input {
type filter hook input priority 0;
ip6 saddr 2001:db8:1f15::/64 accept
ip6 saddr 2001:db8:1f15::9/128 accept
}
}
If you're seeing unexpected behavior with DHCPv6 addresses:
- Check
radvd
and DHCPv6 server configurations for consistency - Verify that
sysctl net.ipv6.conf.eth0.accept_ra
is set appropriately (usually 2) - Inspect DHCPv6 client logs with
journalctl -u systemd-networkd
ordhclient -6 -d eth0
Remember that Ubuntu's default network manager (Netplan) uses systemd-networkd
or NetworkManager as the backend, each with slightly different DHCPv6 implementations.