IPv6 Prefix Delegation: A Troubleshooting Cookbook

Published on

FreeBSD IPv6 Troubleshooting Networking

Why This Post Exists

The main IPv6 setup post shows you the happy path. This post is everything you reach for when the happy path doesn't happen. Most of these are things I've broken, sometimes more than once, on my own router.

The 60-Second Checklist

Before you go deep, sanity-check the obvious:

  1. sysctl net.inet6.ip6.forwarding — should be 1.
  2. ifconfig $ext_if shows a link-local v6 address (fe80::) and the ACCEPT_RTADV flag.
  3. service dhcp6c status says it's running.
  4. service rtadvd status says it's running, on the LAN-side interfaces.
  5. The WAN cable is the WAN cable. (You laugh, but.)

If any of those is off, fix that first; the rest of the post probably won't help.

Symptom: dhcp6c Won't Even Try

If dhcp6c starts but the WAN never sees DHCPv6 traffic:

$ tcpdump -ni $ext_if 'udp port 546 or udp port 547'

Crickets? Check that the interface is actually up and that accept_rtadv is set. Without an RA from upstream, dhcp6c won't send a SOLICIT in statefulonly mode (which is the default for many configs). The fix is usually one of:

Symptom: dhcp6c Tries But Gets Nothing

You see dhcp6c sending SOLICITs, but no ADVERTISE in reply:

$ tcpdump -ni $ext_if -vv 'udp port 547'
... > ff02::1:2.547: dhcp6 solicit
(silence)

Most common causes, in order of likelihood:

Symptom: dhcp6c Got a Prefix, but the LAN Is Quiet

dhcp6c logs say it received a /56, your igc1 has a v6 address — and nothing on the LAN gets one. First, confirm the prefix actually landed:

$ ifconfig igc1 inet6
        inet6 fe80::1%igc1 prefixlen 64 scopeid 0x2
        inet6 2001:db8:cafe:1::1 prefixlen 64

$ netstat -rn -f inet6 | grep igc1

If the global address isn't there, dhcp6c's script didn't apply it to the LAN interface. Check /usr/local/etc/dhcp6c.conf for the prefix-interface blocks, and confirm the script "/usr/local/etc/dhcp6c-script" line points at a script that actually runs ifconfig on receipt.

Symptom: rtadvd Sends Nothing

Even with the LAN address present, clients don't see RAs:

# From the router, look at what rtadvd is sending
$ tcpdump -ni igc1 'icmp6 and ip6[40] == 134'

ICMP6 type 134 is Router Advertisement. If you see no traffic, rtadvd isn't running or isn't bound to that interface. Check:

Symptom: Clients Get Addresses but Can't Resolve

DNS over v6 has two delivery mechanisms:

On rtadvd, RDNSS is enabled with a config file:

# /etc/rtadvd.conf
igc1:\
    :rdnss="2001:db8:cafe:1::1":\
    :dnssl="lan":

On dhcp6s (if you also want stateless DHCPv6 for older clients), point clients at the same address. But honestly: RDNSS works on every modern OS, so start there.

Symptom: Pings Work, TCP Doesn't

Classic Path MTU bug. v6 doesn't fragment in transit; if a packet is too big for a hop, the router sends back icmp6-type toobig. If pf drops that, large TCP packets vanish into the void.

# Make sure pf is letting these through
pass inet6 proto icmp6 all icmp6-type { toobig unreach paramprob } keep state

If TCP works for short responses but hangs on large transfers, this is almost always the cause. Confirm with:

$ ping6 -s 1450 -D ipv6.google.com
$ ping6 -s 1500 -D ipv6.google.com   # may fail with PMTU=1492 or similar

Symptom: Everything Works, Then Doesn't

v6 works for a few hours, then a client's address goes stale. Causes:

The pf Side

v6-specific things that bite:

The tcpdump Cookbook

# DHCPv6 traffic on the WAN
$ tcpdump -ni $ext_if -vv 'udp port 546 or udp port 547'

# Router solicitations and advertisements on the LAN
$ tcpdump -ni igc1 'icmp6 and (ip6[40] == 133 or ip6[40] == 134)'

# Neighbour solicitations / advertisements
$ tcpdump -ni igc1 'icmp6 and (ip6[40] == 135 or ip6[40] == 136)'

# Anything ICMPv6 on a given interface
$ tcpdump -ni igc1 'icmp6'

# Watch only multicast (RAs, NDP)
$ tcpdump -ni igc1 'ip6 multicast'

# Pflog for v6 specifically
$ tcpdump -ni pflog0 'inet6'

Useful sysctls

# See current values
$ sysctl net.inet6.ip6 | grep -iE 'forward|tempaddr|accept'

# Common ones to know
net.inet6.ip6.forwarding             # 1 if router
net.inet6.ip6.accept_rtadv           # 1 to listen for RAs (set per-iface usually)
net.inet6.ip6.use_tempaddr           # 1 to enable privacy addresses
net.inet6.ip6.prefer_tempaddr        # 1 to prefer them on outbound
net.inet6.icmp6.nd6_useloopback      # 1 by default; rarely needs changing
net.inet6.ip6.no_radr                # 1 to ignore default routes from RAs (don't set on a CPE)

When to Stop and Reboot

IPv6 has more state spread across more daemons than IPv4. Sometimes the right move, after you've checked everything reasonable, is:

$ service rtadvd stop
$ service dhcp6c  stop
$ ifconfig igc1 inet6 -alias 2001:db8:cafe:1::1
$ ifconfig igc0 down up
$ service dhcp6c  start
$ service rtadvd start

That sequence brings everything down, clears any stuck addresses, and brings things back up in the right order. It's not a real fix — but the sun's coming up, your kid wants the wifi back, and tomorrow you'll diff the configs to figure out what changed.

The Reading List

Where to Go Next

Stuck on a symptom I haven't covered? Mail me a tcpdump capture and I'll happily add it to the post.

$ subscribe --to newsletter

FreeBSD, pf, and SRE notes — straight to your inbox. No spam, just signal.

Powered by Buttondown. Unsubscribe anytime. Or grab the RSS feed.

Related Posts

← Back to Blog