Which trigger for new IPv6 PE addresses?

Started by drosophila, March 31, 2026, 12:00:53 AM

Previous topic - Next topic
I'm stuck trying to react to the WAN interface getting a new IPv6 privacy extensions address. I've found the "newwanipv6" trigger but that only triggers when the main IPv6 address / prefix has changed. It does, however, not trigger when privacy extension addresses expire / new ones are generated. I need to react to both these events. A cron job would be possible but running that every minute is both wasteful and slow to react. There must be a better way, can somebody please point me in the right direction?

Quote from: drosophila on March 31, 2026, 12:00:53 AMI need to react to both these events.
Why? Maybe we can help you better if you tell us why that should matter.


IMHO a changing PE IPv6 should never matter. And AFIK, OPNsense does not get a PE IPv6 on the WAN interface, even when SLAAC is used.

AFAIK, OpnSense itself uses no privacy extensions for its own outbound connections. With IA_NA, it just cannot, because that would be a /128 and even with IA_PD, it does not, which has been criticised in the past.

Thus, I suspect you try to achieve something different? Dynamic DNS is out of the question, because you would rely on the redundant EUI-64 based parts for that, so what is your intention?
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 450 up, Bufferbloat A+

March 31, 2026, 08:16:14 PM #3 Last Edit: March 31, 2026, 08:19:31 PM by drosophila
Quote from: JamesFrisch on March 31, 2026, 09:52:48 AMWhy? Maybe we can help you better if you tell us why that should matter.
Quote from: meyergru on March 31, 2026, 10:53:52 AMThus, I suspect you try to achieve something different? Dynamic DNS is out of the question, because you would rely on the redundant EUI-64 based parts for that, so what is your intention?
My issue is twofold. On my WAN connection I have at least five addresses, occasionally seven or eight. It's a router-behind-router setup with OPNsense on the "LAN" port of the ISP router. That receives a proper 56 from the ISP and could in theory delegate its prefix to OPNsense but I disabled DHCP6 and use SLAAC so I get proper PEAs on the OPNsense box (it also creates them when I use DHCP6 with PD but never uses them). One needs to enable the relevant tunables first, of course.

To be able to raliably reach the ISP router I also assign a fixed ULA prefix to it that OPNsense also picks up properly. So it has two prefixes and generates one PEA for each. Obviously I don't need the PEA for the ULA but it doesn't matter. Add to this the expiring PEAs and you get two more, plus one that sticks around a bit longer for whatever reason occasionally. With the LLA this are up to eight IPv6 addresses on the WAN IF. This is why I need ways to choose which picker picks from what pool.

Sample ifconfig output with five addresses:
re1: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
description: WAN (wan)
options=2008<VLAN_MTU,WOL_MAGIC>
ether mac:mac:mac:mac:mac:mac
inet 192.168.aaa.aaa netmask 0xffffff00 broadcast 192.168.aaa.255
inet6 fdyy:yyyy:yyyy:yyyy:mac:mac:mac:mac prefixlen 64 autoconf pltime 3600 vltime 7200
inet6 fdyy:yyyy:yyyy:yyyy:pea1:pea1:pea1:pea1 prefixlen 64 autoconf pltime 3600 vltime 7200
inet6 fe80::mac:mac:mac:mac%re1 prefixlen 64 scopeid 0x2
inet6 2xxx:xxxx:xxxx:xxxx:mac:mac:mac:mac prefixlen 64 autoconf pltime 3600 vltime 7200
inet6 2xxx:xxxx:xxxx:xxxx:pea2:pea2:pea2:pea2 prefixlen 64 autoconf temporary pltime 3600 vltime 7200
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
Currently, which one gets picked by the various pickers depends on their sequence, which is essentially random. The kernel does pick the PEA for outbound connections properly regardless of the order they are in, according to curl v6.ipinfo.io (which is a great tool because it provides output when used with curl so it works from the console(!)).

For Dynamic DNS this, however, isn't desirable due to the frequent changes, so that needs to pick the non-PE address. That I can only achieve with the "interface IP" picker, but currently that doesn't let me chose which address to prefer (hence this post https://forum.opnsense.org/index.php?topic=51477.0 for DDNS.). It seems to pick the first global IP it finds, most of the time that will be the non-PEA because that tends to be on top. Fine so far, but:

Second, and I didn't want to bring up the the "Voldemort of IPv6": NAT66. My LAN is nated to the WAN IP and the picker for this seems to not use PEAs unless they're the first in the ifconfig list. I wish it to always use the PEAs, never the GUAs. In fact, it picks the first non LLA it finds, which will often be an ULA, like in the ifconfig output above. That of course results in broken connectivity and must never happen regardless.

Therefore I need the NAT picker to use the global PEA if there is one, preferredly the non-deprecated one, and only fall back to the GUA if there is no PEA. Alas, I cannot instruct the picker to do so. Of course, that must not be hardcoded in the picker because there certainly are cases where you need to NAT between two ULA prefixes.

Thus I've resorted to writing a script that reorders the IP addresses on the interface so that a non-deprecated PEA is on top of the list so the NAT picker will choose that. This probably makes the DynDNS picker pick the global PEA instead of the GUA, but that is less detrimental than NAT picking a non-PEA and less disruptive than NAT picking an ULA.

However, this script has to run every time a new PEA is generated because that essentially randomizes the address list again. This happens hourly. Now I could set up a cron job that either tries to catch it at the proper time (which isn't going to work), or do it every minute, as in my OP.

To sum it up / TL;DR: I want the DynDNS picker to use the GUA, and the kernel and the NAT picker to use the most recently generated global PEA. Sounds simple but seems next to impossible ATM. :)

I do that completely differently: Whatever the outbound IPv6 is, it will always have the same /56 prefix, because I use IA_NA only.

Thus, the lower 68 Bits consist of the interface ID + 64 bits of whatever any client or OpnSense has. In order to make services available, it is best to refrain from privacy addresses (because they change!) and use the (fixed) EUI-64 part. There are many dynamic DNS providers that are capable of chopping off the lower bits and only change the prefix to the incoming connection. I happen to use my own.

Thus, they keep whatever you manually configure the lower bits to be. This makes it possible to have dynamic DNS updates done by OpnSense "in lieu" of any client.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 450 up, Bufferbloat A+

March 31, 2026, 09:06:19 PM #5 Last Edit: March 31, 2026, 09:25:58 PM by drosophila
Quote from: meyergru on March 31, 2026, 08:57:26 PMThere are many dynamic DNS providers that are capable of chopping off the lower bits and only change the prefix to the incoming connection.
Thanks for the hint, I will see if the one I chose (dynv6.com) will do that, which would alleviate the DynDNS issue. If it doesn't, I'll ask what you're using. ;)

However, I'd still need to reorder the addresses in a timely manner to make Voldemort use the correct PEA. :(

Oh, almost forgot: the reordering also breaks the Gateway monitor, which will, for whatever reason, show 100% loss for IPv6 even though the GW is perfectly reachable on the specified ULA address. I guess I'll just throw that out to make space for more important bits in the dashboard, but it shouldn't even be affected by this in the first place...?

Oh, I forgot: With services that actually allow to set a specific IP, you can use this to set the __MYIP__ variable for a custom get request with an interface prefix plus a specific EUI-64:
You cannot view this attachment.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 450 up, Bufferbloat A+

IIRC my service claims to accept custom GET, so I'll be looking into this configuration and see if they actually take it. Thanks! :)

April 04, 2026, 05:50:58 AM #8 Last Edit: April 04, 2026, 05:59:15 AM by drosophila
The good news: custom GET with dynamic host works on dynv6.com. I had to enter the password in the URL string, the variable "__PASSWORD__" that I tried didn't work, but I didn't try other possible variants.
I also found that in the "advanced" configuration, you can set a Dynamic IPv6 host natively without Custom GET.
The bad news: whatever I tried, all of them would use the first matching address it finds, which sadly always are the deprecated ones with the old prefix. So for this, too, I need my reordering script to run promptly. I'll see if it recovers when the prefix times out, but even if it does, that is 1 hour of downtime each time unless the script runs (which it doesn't because I've obviously screwed that up by trying to integrate it with the plugin system *sigh*)

I do not understand your problem with the reordering, because dynv6.com allows you to use the variable "ipv6", which you can have derived from any EUI-64 that you like, like I depicted in my screendump above. You only need to specify the EUI-64 part that you want plus the interface that it should be combined with. No scripting needed.

And you would never, ever use a temporary (dynamically-created) EUI-64, always the "mgmtaddr", because OpnSense would not know when a tempaddr changes, so you must know in advance which EUI-64 to use and which interface it is connected to.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 450 up, Bufferbloat A+

April 07, 2026, 12:17:02 AM #10 Last Edit: April 07, 2026, 01:40:45 AM by drosophila
Quote from: meyergru on April 04, 2026, 09:05:31 AMI do not understand your problem with the reordering, because dynv6.com allows you to use the variable "ipv6", which you can have derived from any EUI-64 that you like, like I depicted in my screendump above. You only need to specify the EUI-64 part that you want plus the interface that it should be combined with. No scripting needed.
The script needs to clean up the mess shown in the annotated attachment. This is how things are every time I get a new prefix. All pickers end up picking the wrong address because they simply go from top to bottom without regarding any attributes or other details. Thus I need to manually move the two desired addresses to the top so that the pickers will choose them. This happens both with the custom GET method with EUI-64 part and the option from the "advanced settings" that allows something similar. The reason is that the EUI-64 part is the same for the old and the new prefix (obviously). Without the script, this will only rectify itself after the old address finally expires.
Quote from: meyergru on April 04, 2026, 09:05:31 AMbecause OpnSense would not know when a tempaddr changes
This, precisely, is my problem and my hope was that I simply missed the correct trigger in the documentation. So it's plainly not possible to do it properly, and all I can do is to keep polling every minute?

Sorry, but I still do not get what the actual problem is:

a. You can tell the dyndns updater to use any (static) suffix you like.
b. You cannot know which temp addresses a client will use - so you cannot update dyndns "in lieu" for a client for a temp address - but that is not neccessary, because there will always be a static IPv6 under which the client can also be reached, so you can use that.
c. Same goes for OpnSense itself, iff that even used temporary adresses.

When you forget about your scripts and formulate the exact problem: what type of dyndns adresses are those that you want to make accessible that are problematic? OpnSense itself or clients? Temp addresses or "static suffixes"?
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 450 up, Bufferbloat A+

April 07, 2026, 03:29:18 PM #12 Last Edit: April 07, 2026, 06:37:00 PM by drosophila
Quote from: meyergru on April 07, 2026, 10:34:27 AMa. You can tell the dyndns updater to use any (static) suffix you like.
Yes, and thanks to you I now know even two methods for doing that. :)
Quote from: meyergru on April 07, 2026, 10:34:27 AMb. You cannot know which temp addresses a client will use - so you cannot update dyndns "in lieu" for a client for a temp address - but that is not neccessary, because there will always be a static IPv6 under which the client can also be reached, so you can use that.
Yes, and while I'd much prefer to use PEAs for ddns, I've accepted this fact for the time being.
Quote from: meyergru on April 07, 2026, 10:34:27 AMc. Same goes for OpnSense itself, iff that even used temporary adresses.
It does use them if the WAN is not configured via DHCP6. And it also picks them over anything else that's configured on the interface, as it should be. But it does so only for its own requests. For NAT66, it uses "whichever is on top of the list", which will almost always be something undesirable like the site-locals or the GUA.
Quote from: meyergru on April 07, 2026, 10:34:27 AMWhen you forget about your scripts and formulate the exact problem: what type of dyndns adresses are those that you want to make accessible that are problematic? OpnSense itself or clients? Temp addresses or "static suffixes"?
As said, I've come to accept that using a PEA for ddns isn't currently feasible, so

- I've settled for using the EUI-64 derived address.

 Because I'm using NAT66,

- the address I want ddns to use is the GUA of the OPNsense box (while NAT66 should use the PEA of the OPNsense box for outbound connections).

The EUI-64 GUA works with ddns, but during the timeout period after the daily prefix change, the old address is kept around for 1 hour and is still usable. During this time, the ddns updater doesn't pick up the new prefix, so the update is delayed. So during this time, the box is not reachable because

- the ISP router updates its forwarding route to OPNsense to the new prefix immediately and therefore the old prefix is no longer reachable from outside, even though it is still valid for outgoing requests, which is why the ddns client doesn't pick up the new prefix.

Therefore, the OPNsense box (resp. the port-forwarded host behind it) is not reachable for this period. After the previous prefix finally times out, ddns picks up the new prefix and it works until the next prefix change.

With my script as cron job, I'd reduce this downtime to at most 1 minute. That's much better but of course still much worse than it could be, plus adds senseless polling overhead all the time.

IOW, if the interface monitor would simply disregard addresses with the "deprecated" tag, things would work without scripted meddling.

With an external provider it seems that even PEAs would work for ddns in conjunction with NAT66, but only if the ISP router would forward everything to OPNsense, or I'd put OPNsense directly at the ISP line. If it would not use deprecated addresses. Not going to do that ATM but something to keep in mind.