The IPv6-PD gateway address in the routing table

Started by LHSFK, February 25, 2025, 10:59:28 AM

Previous topic - Next topic
February 25, 2025, 10:59:28 AM Last Edit: February 25, 2025, 11:01:35 AM by LHSFK
Issue: When delegated IPv6-PD differs from the LAN subnet, the gateway in the IPv6-PD route uses the downstream router's DHCPv6 global address. It should instead use a link-local address (FE80::/10).

Example:

WAN: fc00:0:0:80::/57
LAN: fc00:0:0:80::/64
Delegated IPv6-PD: fc00:0:0:c0::/60
Downstream router's WAN (stateful IPv6): fc00:0:0:80::87fd
Downstream router's link-local address: fe80::be24:11ff:fede:f617

So the gateway in the routing table of IPv6 PD should be fe80: be24:11ff:fede:f617%lan

I discovered an issue: when the firewall is configured with SLAAC-only, the gateway for the delegated IPv6-PD in the routing table still uses a stateful IPv6 address (which I did not enable). This causes external networks to fail to access hosts behind the downstream router, because the gateway for the IPv6-PD route in the firewall's routing table is a non-existent address. Therefore, I believe the link-local address should be used as the gateway, as it remains stable.


As I understand it, a route for a delegated prefix will be added only if either the downstream router requests an IA_NA (and is given a lease) or there exists a static mapping for the downstream router (with matching DUID) (even if the downstream router doesn't request an IA_NA). Otherwise there won't be any route added. I'm not sure why the LLA can't be used.

Do you have a static mapping for your downstream router's DUID? What was the gateway address for the route that got added?

February 25, 2025, 01:21:48 PM #2 Last Edit: February 25, 2025, 01:38:27 PM by LHSFK
Hello, I did not configure static mapping of DUID for downstream routers. This is my configuration:

opnsense wan
        addr fc00::be24:11ff:fe5f:590b/64
        pd  fc00:0:0:80::/57

        lan fc00:0:0:80::1/64
        pd fc00:0:0:f0::/62

Downstream Router  wan fc00::80:be24:11ff:fede:f617
          pd  fc00:0:0:f0::/62

wan dhcpv6
lan track interface
    Optional interface ID  0x1
    X  Allow manual adjustment of DHCPv6 and Router Advertisements

Routing Table: ipv6    fc00:0:0:f0::/62    fc00:0:0:80::2000    UGS    NaN    1500    vtnet0    LAN


Services: ISC DHCPv6: Leases
leases :
No results found!
delegated prefixes:
fc00:0:0:f0::/62    1    d5:6a:78:76:98:6c:9b:86:2b:89:48:4e:9a:01:bd:fa    2025/02/25 19:16:22    2025/02/25 21:16:22    active

Although the address of the downstream router cannot be seen, the address of the downstream router is available

At this point, it will be found that the routing table contains ipv6 pd fc00:0:0:f0::/62 The gateway for 62 is fc00:0:80:2000, but in reality, the downstream router receives the address fc00:: 80: be24:11ff:fede:f617


Ping at the firewall:
root@OPNsense:~ # ping fc00:0:0:80::2000
PING(56=40+8+8 bytes) fc00:0:0:80::1 --> fc00:0:0:80::2000

--- fc00:0:0:80::2000 ping statistics ---
7 packets transmitted, 0 packets received, 100.0% packet loss

You will find that ping is not working and this address does not exist



In order to enable downstream routers to obtain a larger IPV6 subnet, I have activated it "Allow manual adjustment of DHCPv6 and Router Advertisements"

Router Advertisement  Stateless

DHCPV6
    LAN range        ::1            ::ffff
    IPV6 PD range  ::90:0:0:0:0  ::f0:0:0:0:0
    IPV6 PD length 60
DHCPv6 Static Mappings for this interface:
No configuration at all

Routing Table ipv6    fc00:0:0:f0::/60    fc00:0:0:80::2000    UGS    NaN    1500    vtnet0    LAN


Services: ISC DHCPv6: Leases
leases :
No results found!
delegated prefixes:
fc00:0:0:f0::/60    1    d5:6a:78:76:98:6c:9b:86:2b:89:48:4e:9a:01:bd:fa    2025/02/25 19:34:10    2025/02/25 21:34:10    active

Downstream Router pd fc00:0:0:f0::/60   
                  wan fc00::80:be24:11ff:fede:f617/64

I will find that the routing table for the firewall IPV6 PD gateway is FC00:0:80:2000, which is a non-existent address. I'm not sure why it uses a stateful DHCPV6 address as the gateway, even if I haven't enabled it

After my testing, no matter how the gateway for IPv6 PD is set, it will point to a stateful DHCPV6 address (even if it is not enabled or the address is unavailable). I am not sure why link local addr is not used as the gateway

As long as the downstream router receives the SLAAC address, the IPv6 PD gateway issued by the firewall will point to a non-existent address, which makes it invalid for hosts accessing the downstream router from the public network (I am using ULA for testing here, in fact, GUA is the same), because my ISP issued me a dynamic IPV6 address, so I did not manually specify the IPV6 PD gateway, but let the firewall automatically configure it. Otherwise, I would have to change the IPV6 PD every time my ISP changes it, which is very troublesome

fc00:0:0:80::2000 must have been leased to your downstream router at some point - probably prior to you selecting "Allow manual adjustment of DHCPv6 and Router Advertisements". The default range in that case is from ::1000 to ::2000. Any reference to it left over in /var/dhcpd/var/db/dhcpd6.leases ?

February 25, 2025, 01:50:16 PM #4 Last Edit: February 25, 2025, 01:52:05 PM by LHSFK
It does exist in "/var/dhcpd/var/db/dhcpd6. leases", but it cannot be pinged. The downstream router displays the address fc00:80: be24:11ff: fede: f617, which is not "fc00:0:80:: 2000"

root@OPNsense:~ # cat /var/dhcpd/var/db/dhcpd6.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.4.3-P1

# authoring-byte-order entry is generated, DO NOT DELETE
authoring-byte-order little-endian;

server-duid "\000\001\000\001/L\237j\274$\021\004\347'";

ia-na "\001\000\000\000\325jxv\230l\233\206+\211HN\232\001\275\372" {
  cltt 2 2025/02/25 12:41:56;
  iaaddr fc00:0:0:80::2000 {
    binding state active;
    preferred-life 4500;
    max-life 7200;
    ends 2 2025/02/25 14:41:56;
  }
}

ia-pd "\001\000\000\000\325jxv\230l\233\206+\211HN\232\001\275\372" {
  cltt 2 2025/02/25 12:41:56;
  iaprefix fc00:0:0:f0::/62 {
    binding state active;
    preferred-life 4500;
    max-life 7200;
    ends 2 2025/02/25 14:41:56;
  }
}

server-duid "\000\001\000\001/L\237j\274$\021\004\347'";

ia-na "\001\000\000\000\325jxv\230l\233\206+\211HN\232\001\275\372" {
  cltt 2 2025/02/25 12:42:50;
  iaaddr fc00:0:0:80::2000 {
    binding state released;
    preferred-life 4500;
    max-life 7200;
    ends 2 2025/02/25 14:41:56;
  }
}

ia-pd "\001\000\000\000\325jxv\230l\233\206+\211HN\232\001\275\372" {
  cltt 2 2025/02/25 12:42:50;
  iaprefix fc00:0:0:f0::/62 {
    binding state released;
    preferred-life 4500;
    max-life 7200;
    ends 2 2025/02/25 14:41:56;
  }
}

ia-na "\001\000\000\000\325jxv\230l\233\206+\211HN\232\001\275\372" {
  cltt 2 2025/02/25 12:42:53;
  iaaddr fc00:0:0:80::2000 {
    binding state active;
    preferred-life 4500;
    max-life 7200;
    ends 2 2025/02/25 14:42:53;
  }
}

ia-pd "\001\000\000\000\325jxv\230l\233\206+\211HN\232\001\275\372" {
  cltt 2 2025/02/25 12:42:53;
  iaprefix fc00:0:0:f0::/62 {
    binding state active;
    preferred-life 4500;
    max-life 7200;
    ends 2 2025/02/25 14:42:53;
  }
}

root@OPNsense:~ # ping fc00:0:0:80::2000
PING(56=40+8+8 bytes) fc00:0:0:80::1 --> fc00:0:0:80::2000

--- fc00:0:0:80::2000 ping statistics ---
7 packets transmitted, 0 packets received, 100.0% packet loss
root@OPNsense:~ # ping fc00::80:be24:11ff:fede:f617
PING(56=40+8+8 bytes) fc00:0:0:80::1 --> fc00::80:be24:11ff:fede:f617
16 bytes from fc00::80:be24:11ff:fede:f617, icmp_seq=0 hlim=64 time=0.376 ms
16 bytes from fc00::80:be24:11ff:fede:f617, icmp_seq=1 hlim=64 time=0.306 ms

--- fc00::80:be24:11ff:fede:f617 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.306/0.341/0.376/0.035 ms

It appears that the lease for that ::2000 address was timestamped just 9 minutes before your post, so it seems that your downstream router must be requesting a IA_NA. Not being able to ping it doesn't mean it's not there - it may be filtering your ping...

February 25, 2025, 03:02:31 PM #6 Last Edit: February 25, 2025, 03:05:16 PM by LHSFK
I analyzed the code at "https://github.com/opnsense/core/blob/master/src/opnsense/scripts/dhcp/prefixes.php" using deepseek-r1. It appears to generate routing tables by directly extracting the ia-na (address assignment) and ia-pd (prefix delegation) fields from "/var/dhcpd/var/db/dhcpd6.leases". However, my downstream router's WAN interface allows only one IPv6 address. Likely due to SLAAC addresses taking higher priority or another reason, when my downstream router obtains a SLAAC address, it immediately deprecates the DHCPv6-assigned address, resulting in ping failures. Since "/var/dhcpd/var/db/dhcpd6.leases" cannot capture SLAAC addresses (as prefixes.php relies solely on this file to update routes), the gateway for delegated prefixes (IA_PD) remains stuck on the deprecated DHCPv6 address.I hope opnsense engineers can optimize it.

Your downstream router seems a bit broken, in my opinion - others may differ, though.......