With IPv6, how to get both GUA SLAAC and a single ULA DHCPv6 address?

Started by espenu, July 07, 2026, 08:09:26 AM

Previous topic - Next topic
In all my VLANs my clients currently get a GUA address using SLAAC.
But for internal server communications I don't want to risk a prefix change from my ISP to break internal communications.
So, I've settled on using DHCPv6 to give out ULA addresses. Each server is given a dedicated address added to its host entry in dnsmasq.
Opnsense is given a ULA in each subnet as a virtual IP on each interface. In Router Advertisements the mode is set to assisted.
This partially works, as the clients get both a SLAAC GUA and the DHCPv6 ULA. However, since it's not possible to set RA modes per address, only per interface, I also get a ULA SLAAC address.
The extra address wouldn't have been a big deal if it wasn't for the fact that the servers use the ULA SLAAC as their source address when communicating across VLANs.
Because of that, my firewall rules, which rely on the hostname entries, kind of break.

The only "solutions" I've found are:
- Use the ULA SLAAC for source in firewall rules, but this is messy and the SLAAC may be using privacy extensions so the address is not deterministic (which is why I wanted DHCPv6 in the first place).
Disabling privacy extensions also makes the GUA EUI-64 and therefore exposes the MAC (not a deadly critical issue, but I want to avoid it). It also requires custom configuration depending on server OS, which I don't like.

- Use the whole network prefix as the source in firewall rules. This is what I currently do, but it makes my rules much "looser" than I would like.

The best solution would be if I could only set the RA A flag to only be used for the GUA prefix. But as I understand it that's not possible in Opnsense because settings apply to all addresses on the selected interface.
Or are there ways to do this that I just haven't found?
The "for all addresses in the interface" approach is also annoying with DHCPv6, because if I use the constructor and only specify the end addresses for the range, it will give out DHCPv6 for both GUA and ULA, when I only want the ULA. Specifying the whole range addresses solves this of course, but it's still a bit annoying.

Are there solutions to this issue? Am I just thinking about the whole thing in the wrong way?


A possible alternative would be to use ULA only for internal, and NPTv6 for internet...

Quote from: Bob.Dig on July 07, 2026, 09:33:24 AMWhy not using good, old IPv4 for internal things?

I am also fond of that, see: https://forum.opnsense.org/index.php?topic=45822.0 for an in-depth discussion.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, Leox LXT-010H-D

1100 down / 450 up, Bufferbloat A+

Quote from: Bob.Dig on July 07, 2026, 09:33:24 AMWhy not using good, old IPv4 for internal things?
I could, but in the process of learning IPv6 better I wanted to run fully dual stack in the homelab. I don't think what I'm trying is too far outside of normal IPv6, so it should work.
If I'm doing something wrong I would like to learn what the correct way is.

With IPv6 you can set any number of addresses you wish, so it should be possible to add the ULAs in addition to the SLAAC GUAs. The only issue is that the GUI doesn't expose this feat (at all: even in the static configuration, it allows only exactly one IPv6 address to be set). I'm looking into disabling LLA autogeneration and instead manually assigning LLAs to match the ULAs so I can see which machine is burping in the logs without translating MACs all the time. But I need to enter two addresses for this to work though the GUI. Command line or script works of course, but it's a GUI-based system so...

Quote from: meyergru on July 07, 2026, 10:48:28 AM
Quote from: Bob.Dig on July 07, 2026, 09:33:24 AMWhy not using good, old IPv4 for internal things?

I am also fond of that, see: https://forum.opnsense.org/index.php?topic=45822.0 for an in-depth discussion.

I get that, and technically I don't NEED IPv6 for internal communication.
It's an interesting exercise in understanding IPv6 better. As I understand it there is nothing "wrong" with my approach here, which is why it's frustrating that it almost works, but not quite.

I've finally had a chance to properly read through the thread you linked to, and there is a statement that I can't get to match with what I'm seeing from post 72:
"That is were ULA might be helpful. Then again, with dual stack, they will not be used when an IPv4 DNS entry exists."

But on my Debian machines it seems like ULA is prioritized over IPv4.
At least if I ping a host with both defined in DNS it's the ULA that's used.

Quote from: drosophila on July 08, 2026, 04:15:49 PMWith IPv6 you can set any number of addresses you wish, so it should be possible to add the ULAs in addition to the SLAAC GUAs. The only issue is that the GUI doesn't expose this feat (at all: even in the static configuration, it allows only exactly one IPv6 address to be set). I'm looking into disabling LLA autogeneration and instead manually assigning LLAs to match the ULAs so I can see which machine is burping in the logs without translating MACs all the time. But I need to enter two addresses for this to work though the GUI. Command line or script works of course, but it's a GUI-based system so...
You can add additional ULAs as virtual IPs on each interface.

Quote from: espenu on July 12, 2026, 12:38:44 AM
Quote from: drosophila on July 08, 2026, 04:15:49 PMWith IPv6 you can set any number of addresses you wish, so it should be possible to add the ULAs in addition to the SLAAC GUAs. The only issue is that the GUI doesn't expose this feat (at all: even in the static configuration, it allows only exactly one IPv6 address to be set). I'm looking into disabling LLA autogeneration and instead manually assigning LLAs to match the ULAs so I can see which machine is burping in the logs without translating MACs all the time. But I need to enter two addresses for this to work though the GUI. Command line or script works of course, but it's a GUI-based system so...
You can add additional ULAs as virtual IPs on each interface.
Thanks for the info, though I don't see how this ties in with the ifconfig setup. The name suggests that the "virtual" addresses are in some way "lesser" than the "main" address. Maybe I'm wrong on this, I'd need to try it and see what ifconfig will end up looking like. I expect all sorts of breakage with this setup if I enter an LLA as "main" (since this should be available first) and the real ULAs as "virtual". Probably it all depends on how, when and where they end up getting set and this may even change on version upgrades. Maybe it's just a naming thing and all addresses get added in one swoop regardless of what they're called. I'll try once I can afford extended debugging downtime.

Edit: so I did some preliminary testing and my initial concerns seem to have been correct: the additional addresses are "lesser" than the primary address and do not get assigned at the same time / with the same priority. For reachability configurations this does not matter much, but the "primary" address is used for outbound connections and NAT, unless routing says otherwise or the addresses get reordered after the fact. For a static setup this is no problem, as I can simply assign my intended LLA as "primary" address and the true ULA as "alias". The system notices this and doesn't autogenerate another LLA even if auto-LLA is enabled. This, however, means that the global IP must be fully static, as the aliases support no dynamic assignments AFAICS, so either one must use GUA with a permanent prefix, or ULAs. This is OK on LAN, but is a real showstopper on WAN: an LLA assigned to WAN as alias is not assigned in time to allow SLAAC to use it, so I cannot disable auto LLA generation - which is the entire point of the exercise. Instead I end up with either an auto-LLA in addition to my own, or no dynamic IP address at all, as SLAAC won't have an LLA to work with when it is asked to negotiate. I'd therefore need a way to run SLAAC after the "alias" address is assigned instead of before - or have the aliases allow SLAAC so the primary address can be static. Of course, I can set up a script that removes the autogenerated LLA once the aliased one is assigned, but this would be yet another modification to keep in mind, track and reestablish on a fresh install.

It would be cool if the config backup would allow me to specify a list of additional files to include in the backup, so I could place such evil hacks there. :)

(again) ULA + NPTv6 seems like the obvious solution if you want to use ULAs internally with a dynamic GUA prefix for internet access. Have you even considered it? Hacks are likely to come back and bite you later...