I thought I'd revisit this topic in 26.1 to see if any new developments (maybe in and around dhcp6c?) can help here.
WAN is set to DHCPv6 with "Request prefix only" for IPv6. This gets distributed via RAs to clients doing SLAAC.
Problem: When either the lease is lost or the WAN flaps, this causes the RA daemon (radvd or dnsmasq) to send a message with preferred lifetime=0 to deprecate the prefix. The issue is that in many cases the prefix is not actually lost. It's just that the ISP has issued a reboot command to the modem, such as for periodic maintenance. When the modem comes back up and we get a new or renewed lease, the same prefix is given to OPNsense.
The problem now is that clients have already marked the prefix as invalid so even if they receive subsequent RAs for the same with new valid & preferred lifetimes, they refuse to generate new temporary addresses and the latest one remains in 'deprecated' state. The client falls back to the stable GUA for outbound connections, if it's available, else would lose IPv6 connectivity altogether.
A new temporary address is never created until/unless the client interface is reset or the client is rebooted.
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 24:xx:xx:xx:77:cd brd ff:ff:ff:ff:ff:ff
inet 172.21.30.100/24 brd 172.21.30.255 scope global dynamic noprefixroute br0
valid_lft 74228sec preferred_lft 74228sec
inet6 2601:xx:xxxx:3163:423d:7f49:624f:8fb2/64 scope global temporary deprecated dynamic
valid_lft 86379sec preferred_lft 0sec
[...]
inet6 2601:xx:xxxx:3163:xxxx:xxx:xxxx:xxx/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 86379sec preferred_lft 86379sec
inet6 fe80::xxxx:xxxx:xxxx:fb89/64 scope link noprefixroute
valid_lft forever preferred_lft forever
'radvd' has an option 'DeprecatePrefix' which can be turned off, but this doesn't help in this scenario. It only prevents the prefix deprecation when the RA daemon (or OPNsense) is being shut down or restarted.
OPNsense has an option under Interfaces->Settings (advanced mode)->Prevent release, but this only tells the ISP to hold the lease.
My question is, does 26.1 bring any additional capabilities that we can leverage to stabilize the prefix on WAN for transient events like modem power loss or reboots? I'm thinking we could have an option to tell the system that it should not drop prefixes from the interfaces within some configurable interval, say 5 minutes, in case the same prefix is seen again shortly? That way the RA daemons won't notice its temporary loss and won't send a deprecation event.
Thoughts?
tl/dr; we are missing an option to prevent RA daemons from prematurely deprecating a prefix that is still active but has been temporarily dropped from interfaces due to some power loss event or modem reboot.
I use my own daemon for this, which proxies the router advertisements from the ISP.
That means there is no truth besides the ISP, but it also means you won't have IA_PD and DHCPv6. You proxy the same SLAAC on-link prefix to all interfaces. (only SLAAC means no DHCPv6 quirks)
I never have any issues even if the WAN is flakey since it's transparent.
https://docs.opnsense.org/manual/ndp-proxy-go.html
Just an alternative approach to this all.
@Monviech I read through the document as well as the readme on your GitHub and I have a few questions, but I also hope to continue discussion on what OPNsense can do separate from this plugin. I feel that dhcp6c needs an option to not break SLAAC in case of unchanging dynamic prefixes.
I'd love to get the developers' inputs on what can be done and potentially get something onto the roadmap.
---
If I understood the proxy correctly, it would distribute the single prefix (e.g. 2001:db8::/64) so that all the network hosts appear to be on the same IPv6 subnet but could still be filtered in pf on a per-VLAN basis due to the dynamic aliases that the proxy populates.
Am I correct that the proxy maintains L2 and L3 isolation between my VLANs and from my ISP as well, but the ISP gets to directly know how many GUAs (hosts) I have? The proxy holds them and responds all icmpv6/ND messages upstream on my clients' behalf? Does the ISP see any other information, such as client MACs, or does the proxy mask them as well?
My ISP apparently floods RAs like a firehose:
root@firewall:~ # tcpdump -i igc1 'icmp6 and icmp6[0] == 134'
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on igc1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
16:04:16.420874 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:16.897641 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:19.449256 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:20.377237 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:23.209756 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:23.878049 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:26.461349 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:27.009106 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:30.098075 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
16:04:30.902112 IP6 fe80::xxx:xxxx:xxxx:99 > ff02::1: ICMP6, router advertisement, length 128
...
Does the proxy buffer the local network from the RA storm, and does it put additional load on my poor Celeron? :)
Next, I see that there are 3 prefixes advertised by the ISP (two ULAs and a GUA):
root@firewall:~ # tcpdump -vvv -i igc1 'icmp6 and icmp6[0] == 134'
tcpdump: listening on igc1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
16:36:47.317680 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 128) fe80::xxx:xxxx:xxxx:99 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 128
hop limit 64, Flags [managed, other stateful], pref medium, router lifetime 1800s, reachable time 90000ms, retrans timer 1000ms
source link-address option (1), length 8 (1): xx:xx:xx:xx:xx:99
0x0000: xxxx xxxx xx99
mtu option (5), length 8 (1): 9192
0x0000: 0000 0000 23e8
prefix info option (3), length 32 (4): fd00:0:d:6::/64, Flags [onlink], valid time 2592000s, pref. time 604800s
0x0000: xxxx xxxx xxxx xxxx xxxx 0000 0000 fd00
0x0010: 0000 000d 0006 0000 0000 0000 0000
prefix info option (3), length 32 (4): 2001:xxx:xxxx:145::/64, Flags [onlink], valid time 2592000s, pref. time 604800s
0x0000: xxxx xxxx xxxx xxxx xxxx 0000 0000 2001
0x0010: xxxx xxxx 0145 0000 0000 0000 0000
prefix info option (3), length 32 (4): fd00:0:101:61::/64, Flags [onlink], valid time 2592000s, pref. time 604800s
0x0000: xxxx xxxx xxxx xxxx xxxx 0000 0000 fd00
0x0010: 0000 0101 0061 0000 0000 0000 0000
Does the proxy configure each of these unnecessary ULAs downstream?
If using the proxy without radvd, how does it configure the clients? Does it act as an RA daemon itself?
Hi everyone, I think this is a good way to use IPv6. I use OpenBSD with this configuration; it's very configurable.
If the prefix changes, it's easy to fix.
I don't know if Opnsense can configure something like that
https://eradman.com/posts/ipv6-strategy.html#:~:text=Use%20rad(8)%20to%20distribute%20the%20stable%20addresses,egress%20inet6%20from%20fd00:51::/64%20nat%2Dto%202603:7081:5506:d885::/64%20source%2Dhash.
Thanks for sharing @Javier, it was a good read and I bookmarked it. I share that administrator's frustrations with regard to dynamic prefixes and tracking SLAAC clients. A silver lining though: the hostwatch service can potentially help with client tracking by enriching DNS with SLAAC addresses, for instance, in future OPNsense releases. Also, Dnsmasq can already register SLAAC hosts as long as they are using DHCP(v4) and also not using privacy extensions.
However this method is nothing but ULA addressing with NAT(66), I think. It skirts the problem I mentioned and I'd rather fix it at the source because one of my goals with IPv6 is to not use NAT.
I asked a similar question regarding NPTv6 (https://forum.opnsense.org/index.php?topic=45822.msg255218#msg255218) and the issue is that ULA addressing would not be used at all for outbound connections when IPv4 is also available (which on my network it is).
Thanks to you. It's just an idea, it involves using IPv6 like IPv4. It works well.
Such a configuration does not prioritize IPv4 over IPv6, IPv6 connections are used when a server supports them. This is normal.
When using a pool with a prefix, each local client accessing the internet is assigned an address within the pool, each client has a different address. I don't know if you understand the concept.
match out on egress inet6 from (igc1:network:2) to any nat-to 2a01:xxxx:xxxx:xxxx::/64 source-hash 0x1ab50493a660a20f6dbcbe662ee9fd
ftp -o - -V -M https://myipv6.addr.tools/
2a01:xxxx:xxxx:xxxx:f277:1996:89b8:81ce
Quote from: Javier® on March 22, 2026, 01:11:44 AMI don't know if you understand the concept.
That's very likely :)
I understood that source-hash means each client gets a unique address from the NAT pool: https://www.openbsd.org/faq/pf/pools.html
I'm still missing something about why the client chooses the (from its perspective) ULA address when it has an IPv4.
Well, the problem is that the connection is now IPv4 and IPv6. For me, managing the local network with ULA is easier, just like with IPv4, and offers greater control. If only IPv4 or IPv6 existed, we wouldn't have this problem.
It's easier to reach a host the way it's always been done with IPv4
Having each customer with only one LLA address and two ULA addresses is cleaner
Stateless Address Autoconfiguration (SLAAC, SOII)
MacOS and OpenBSD use Temporary and Semantically Opaque Interface Identifiers by default. Ubuntu Linux uses stable addresses for wired links, and temporary for wireless interfaces. FreeBSD and Alpine Linux use EUI64.
Complicated :)
This seems fuzzy. I asked ChatGPT (but I don't trust it):
Quote1. ULA vs Global IPv6
If the client only has a ULA (fc00::/7) and the destination is a global IPv6 address, RFC 6724 technically prefers matching scopes. That can:
- De-prioritize ULA for global destinations
- But many real-world stacks still try IPv6 first if it appears usable
So I guess it depends a lot on the client.
I know that Happy Eyeballs will choose the faster of the two, but I didn't think that clients would even try the ULA route if there is no GUA and IPv4 was available.
(And of course, if the destination is IPv6 only then it can't use IPv4.)
---
Anyway, another good alternative method to keep in my toolbox. Thanks again.
To reiterate though the only problem I'm seeing with DHCPv6-PD so far is the premature deprecation of the prefix when the modem reboots and gives me the same prefix again. I think there is a bad assumption built into the stack that dynamic IPv6 means a new prefix every time. That's just not true.
One of the biggest problems with IPv6 is ISPs, in theory, they should assign a fixed prefix.
The only thing I've noticed with this configuration is that IPv4 DNS is used more. But the faster of the two still works, and it does depend a lot on the client.
NAT in IPv6 isn't from ULA to global, it's global to global, I think.
Forgive me if I've been overly enthusiastic.
Thank you OPNenthu
Quote from: Javier® on March 22, 2026, 02:30:25 AMForgive me if I've been overly enthusiastic.
Not at all. I welcome the suggestions, and thank you.
And yes people here tell me all the time how my ISP is terrible for not following RIPE recommendations for a static /48. I think this forum is heavily skewed toward non-U.S. countries where ISPs are maybe more consumer friendly and less profiteering :) My ISP is one of the larger ones here and they commonly do this, unless you pay for a business plan.
My ISP delegates a dynamic 56 prefix, and it hasn't changed since I started using OpenBSD with dhcp6leased.
I'd like to open a GH request for the option to not signal a prefix deprecation if the same prefix is seen again within X minutes, but I'm not sure how all the various components interact in this regard. Even if I'm using DHCPv6, the ISP is still sending RAs and those could also signal a deprecation with preferred liftime=0.
Is this a stupid request, or a feasible one?
--
Also, @Monviech my questions about ndp-proxy-go were meant in good faith. I wasn't trying to be critical. Would really like to know:
- Are the ULA prefixes able to be omitted from distribution downstream?
- Is the high rate of RAs (I see up to 2/sec) a performance concern? Can those be rate limited to downstream?
- If the ISP sends an RA with PreferredLifetime=0 to signal a deprecation, do I have essentially the same problem?
- What information (if any) does this method give to the ISP about my network internals?
Thanks!
Your ISP looks weird I wouldnt use the proxy with them.
It proxies all prefixes that are contained inside the RAs. No way to exclude anything if RAs are proxied.
You couldnt even use radvd together with the proxy since with its constructor mode it also advertises all WAN side prefixes.
Mac addreses are not masked since the EUI-64 Addresses (lla, ula, gua) are generated automatically by clients, and it contains the MAC address anyway.
With any setup your ISP knows all of your devices, you would have to NAT66 to mask them completely.
If you dont trust the ISP and it does weird stuff get a different one essentially.
Thank you! Good that I asked.
The EUI-64 issue is workable, I anyway disable them on web clients. Mobile OSes have privacy features and MAC randomization already enabled. The desktop/laptop machines get configured to use stable privacy addresses with privacy extensions on top. (This is what breaks when those pesky RAs with preferred lifetime=0 come in.)
The ULA routes that the ISP tries to install are definitely not needed. DHCPv6 is preventing them from being configured on the LAN, but the routes still show up on the WAN interface.
WAN-dhcpv6-pd.png
I'm not sure if those are coming from DHCPv6 or from rtsold which is running in the background. Is there a way to disable rtsold on WAN from the OPNsense UI? In Linux I could use a sysctl to selectively disable it for an interface but in FreeBSD I think it's a global systctl (net.inet6.ip6.accept_rtadv=0) which would kill my internal network.
EDIT: I added the tunable to not accept RAs and the ULA routes still got added, so must be from DHCPv6.
--
It seems I might be alone with the prefix deprecation issue. I'll give it some more time to see if any discussion develops around this before submitting a ticket, but am hoping to save the embarrassment of raising a nonsensical request :)
Quote from: Javier® on March 21, 2026, 11:25:09 PMHi everyone, I think this is a good way to use IPv6. I use OpenBSD with this configuration; it's very configurable.
If the prefix changes, it's easy to fix.
I don't know if Opnsense can configure something like that
https://eradman.com/posts/ipv6-strategy.html#:~:text=Use%20rad(8)%20to%20distribute%20the%20stable%20addresses,egress%20inet6%20from%20fd00:51::/64%20nat%2Dto%202603:7081:5506:d885::/64%20source%2Dhash.
I don't think we have an equivalent to 'nat-to ... source-hash' in the FreeBSD favor of pf.
If I'm not mistaken it can be approximated with a combination of stateless NPTv6 and privacy addresses on the clients. With an EUI-64 address, NPTv6 will directly translate and expose the host bits. As long as a privacy ULA is active on the client, it should be the one preferred for egress and NPTv6 will preserve the privacy bits. There would be no way to mask the host bits at the firewall level unless regular Outbound NAT is used for the WAN address (?)
Am I on the right track?
@franco, I just noticed this https://github.com/opnsense/core/issues/10048
In your opinion should I just go ahead and configure my internal interfaces with static ULAs and use NPTv6 for outbound? There are two issues that I don't know if the project will be able to accommodate in the short term (or at all, in the case of #1):
1. As per RFC4941 some client OSes (at least Windows 10 & Linux from what I've tested) take a literal interpretation that they should not revive a deprecated prefix. So even if the same prefix is seen again on WAN and a fresh RA is sent with positive valid & preferred lifetimes, those clients will not regenerate temporary addresses. This effectively breaks SLAAC, or at least a subset of it.
Impact: mostly workstations and clients that stay running for long durations without sleep or reboot. In order to observe the issue, the prefix must be deprecated while the client is running and the client must be powered on long enough for the next temporary SLAAC address to be due for generation (usually each 24 hours by default in most OSes).
2. As per the GH ticket above, adding a ULA prefix as a VIP to the internal interface for RA distribution also breaks when WAN loses its prefix. Thus VIP ULAs cannot be relied on for internal networking.
I think the combination of those means that, at present, the way for people with dynamic prefixes to get stable internal SLAAC is to not track the WAN at all, and to not use ULA VIPs. Instead we have to statically configure the interfaces with ULAs and rely on prefix translation for internet access.
Is this a fair assessment, and, is there anything I can add in GH at this time that could reasonably be accepted and developed by OPNsense to help with this? (I understand dynamic prefixes are not a high priority for the project, so I don't mean to come off pushy here. Just asking.)
Thanks for considering.