Bringing the tunnel up is the easy half. I have watched a site-to-site link stay established for days while every host on the far LAN got silence back, because the delegated prefix behind that gateway was configured on an interface but never routed into the tunnel. The tunnel addresses answered pings the whole time, which is exactly why nobody looked at the prefix. Here is the order I check when a delegated IPv6 prefix has to cross a site VPN: the prefix map, the traffic selectors, forwarding and firewall, then the return path.

Write the prefix map before you touch the tunnel

Prefix delegation hands a block to the router that requested it. It does not install a route on the peer, extend that block on-link, or tell the far gateway what lives behind the requesting router. Those three things are yours to configure, and they belong in an address plan before any config file changes.

For each site, record the delegated prefix, the /64 actually in use on the LAN, the tunnel addresses and the owner of every route. The provider delegates 2001:db8:a1::/56 to site A, which serves 2001:db8:a1:10::/64 on its LAN; site B keeps 2001:db8:b2::/64. If site A serves only that one /64, both ends should name 2001:db8:a1:10::/64 rather than the whole /56.

Two mistakes show up almost every time. One is treating the remote prefix as on-link, bridging it or putting it on the tunnel interface so the gateway answers neighbour solicitation for hosts it cannot reach. The other is advertising the whole /56 when only one /64 is configured: the route table claims the block is reachable and most of the addresses black-hole.

Match both ends' traffic selectors to the routes

IKEv2 and WireGuard both refuse mismatched traffic, quietly enough that the tunnel still looks healthy.

In strongSwan the selectors are explicit. On site A:

conn a-to-b
    left=2001:db8:ff::1
    leftsubnet=2001:db8:a1:10::/64
    right=2001:db8:ff::2
    rightsubnet=2001:db8:b2::/64
    auto=start

Site B's conn mirrors the two subnets. When they disagree, the responder rejects the CHILD_SA with TS_UNACCEPTABLE, so the child SA never comes up even though the IKE_SA did. On both sides the configured subnet has to equal what the local kernel routes toward the tunnel.

WireGuard carries the same information in AllowedIPs, with one twist: AllowedIPs is a source filter on receive as well as a route on send. If site B's peer entry for site A omits 2001:db8:a1:10::/64, packets from site A arrive on a valid handshake and are dropped as not allowed. That produces the familiar pattern of a handshake that keeps renewing while no reply ever leaves. Compare both ends with wg show wg0 allowed-ips. Re-check that list whenever the delegation changes; a stale /64 keeps the session up and the new prefix unreachable.

Rule out forwarding, firewall and MTU first

Before reading another log line, confirm the gateways forward at all. sysctl net.ipv6.conf.all.forwarding has to return 1 on both, applied to the tunnel and LAN interfaces too. One trap comes attached: once forwarding is on, an interface with accept_ra=1 stops accepting router advertisements from the provider, so the box can lose its upstream default route while routing perfectly inside the tunnel. Set accept_ra=2 where a provider RA is still needed.

Firewall rules then have to permit the prefix in both directions, and ICMPv6 has to survive: neighbour discovery, packet-too-big and destination-unreachable are not optional. Drop them and path MTU discovery breaks, giving you connections that open and then stall on the first large response. A minimal pair of rules looks like this:

nft add rule inet filter forward ip6 saddr 2001:db8:a1:10::/64 ip6 daddr 2001:db8:b2::/64 accept
nft add rule inet filter forward ip6 saddr 2001:db8:b2::/64 ip6 daddr 2001:db8:a1:10::/64 accept
nft add rule inet filter forward icmpv6 type { packet-too-big, nd-neighbor-solicit, nd-neighbor-advert } accept

MTU sits behind that. A tunnel shrinks the usable MTU below 1500, and IPv6 requires every link to carry at least 1280. Small pings pass, an SSH session freezes on a large burst, and /proc/net/snmp6 shows packet-too-big messages that never come back. Set the tunnel MTU explicitly, or clamp TCP MSS in the mangle table, and let the ICMPv6 that reports the smaller MTU return.

Test the return path, not the tunnel address

The failure that costs the most time is one-way routing. Each gateway routes the remote prefix into the tunnel, but hosts reply through their own default gateway because that is where their /64 lives. Getting a packet to the destination is half a path.

What you seeLikely causeFirst check
Tunnel up, every host silentremote prefix not routed into the tunnelip -6 route get on both gateways
Handshake renews, no repliessource prefix missing from selectors or AllowedIPsipsec statusall, wg show allowed-ips
Small pings pass, transfers stallMTU or ICMPv6 packet-too-big filtered/proc/net/snmp6 counters
Old prefix still worksstale /64 left in routes or selectorsdelegation lease and route table

Two commands settle most of it. On site A, ip -6 route get 2001:db8:b2::53 from 2001:db8:a1:10::5 shows which interface a reply from that source would use; run the mirror check on site B. Then generate traffic from a host rather than the gateway and compare counters on both ends.

If neighbour solicitation for the remote prefix appears on the tunnel, that prefix is on-link somewhere it should not be; fix that before adjusting routes. Proxy NDP covers cases where bridging is genuinely required, not a substitute for a route.

Plan for the prefix changing under you

Prefix delegation is a lease between the delegating and requesting router, and a renewal can return a different block: a different /56 after a provider migration, or a shorter lease than the tunnel has been up. Every place that names the old prefix goes stale at once: routes, selectors, AllowedIPs, firewall rules, DNS records and any monitoring that hardcodes literal addresses. The message flow is in RFC 8415.

Where the prefix is expected to move, keep an internal addressing plan that does not depend on it and translate at the border. NPTv6 is the stateless option and keeps internal policy readable, but it is prefix translation, not a magic layer: /64 boundaries have to line up, checksums get adjusted, and applications that embed literal addresses still break. If you keep provider addresses end to end, record the lease behaviour and a change procedure in the address plan.

Finish with a test that survives time: a permitted host on each LAN reaches a service on the other LAN, the reply returns through the tunnel, and the same pair still works after a tunnel restart and a delegation renewal. If the last part fails, the design depends on state that will not survive the week.

Pennadoù liammet