Trying to understand IPv6 ULA on OpenWRT

Hi! I recently started to pay more attention to the IPv6 part of my network, I mostly used IPv4 for LAN communicating and usually ignored the IPv6 addresses.

I have both, SLAAC and DHCP6 enabled on my network so my devices get 5 IPv6 addresses:

    inet6 fd00:x:x:x:x:x:x:cb1d/64 scope global dynamic noprefixroute 
       valid_lft 5399sec preferred_lft 2699sec
    inet6 2a0c:x:x:x:x:x:x:x/64 scope global tentative dynamic noprefixroute 
       valid_lft 5399sec preferred_lft 2699sec
    inet6 2a0c:x:x:x::x/128 scope global tentative dynamic noprefixroute 
       valid_lft 43199sec preferred_lft 43199sec
    inet6 fd00:x:x:x::x/128 scope global tentative dynamic noprefixroute 
       valid_lft 43199sec preferred_lft 43199sec
    inet6 fe80::x:x:x:x/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

Tell me if I'm wrong, but top to bottom:

fd00:..../64 slaac ULA addres 
2a0c:..../64 slaac global addres
2a0c:..../128 dhcp global addres
fd00:..../128 dhcp ULA addres
fe80:..../64 auto-generated link-local normally not used

It all works without a problem to get to the internet. The problems comes when I want a reliable way of identifying a device via IPv6. I know I'm supposed to use the ULA but:

  • How does de SLAAC ULA generate? It does so randomly? Only the first time depending from the RA that the router sends? Can I make that a device always generates the same one?
  • How does de DHCP ULA gets decided? In IPv4 DHCP its very clear what IP will have each device as you can specify it manually, but in IPv6 I can only specify DUID/IAIDs and the IPv6 Token. Does any of those options affect the ULA or only the global address?

Thanks!

SLAAC is mac based so usually the same.

My Important clients have DHCPV6 GUA addresses I use static leases so I use dns to connect to those clients

That way I do not need ULA

Usually? How/why does it change in the same network?

I'm trying to not use the GUA as it changes over time and I don't want to depend only on DNS. Also that system will fail in the event that the router loses IPv6 connectivity to the ISP, so is not a valid solution to me.

I want to have connection between devices isolated from the Internet and over a VPN tunnel with the same IP

When you have duplicate mac addresses in your network

DNS is exactly designed to be used for changing addresses.

But use whatever you want.

SLAAC GUAs type depends completely on the configuration of the host machine generating them. They can be EUI64-based, stable or privacy-based temporary addresses (https://datatracker.ietf.org/doc/html/rfc8981). If your host machine is running Linux, then you can see the settings with

$ sysctl net.ipv6.conf | grep use_tempaddr
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2
net.ipv6.conf.enp11s0.use_tempaddr = 2
net.ipv6.conf.lo.use_tempaddr = -1
net.ipv6.conf.macvtap0.use_tempaddr = 2
net.ipv6.conf.wlp12s0.use_tempaddr = 0

where the values are described at https://docs.kernel.org/networking/ip-sysctl.html.

On Windows hosts, the default (not sure how to change it) is the same as Linux use_tempaddr=2. BSD/Mac probably some weird config file somewhere.

The token will determine the host portion of the GUA and ULA DHCPv6 address. I just set the IPv6 token for my computer to b00b and rejoined the network. My DHCPv6 leases are now:

2601:xxxx:4681:b580::b00b/128
fd8f:9fe8:feb3::b00b/128

EDIT: I set a static lease on the router, not the computer.

config host
	list mac 'FC:00:00:36:3A:1B'
	option hostid 'b00b'

I do not set anything at my computer but set a static lease, the hostid for IPv6 determines the host portion

config host
	option name 'PCGijs-X870'
	option duid '000100012F170BE960CF84237E16'
	option mac '60:CF:84:61:7E:32'
	option dns '1'
	option ip '192.168.0.59'
	option hostid '59'
	option leasetime '6h'

But using DNS is easier :wink:

Going back to first principles might clarify things a little.

The classes of ipv6 addresses are identified by the first (left hand) block of four hex digits of the ipv6 address. An identifying block such as this is the first block of the prefix. A prefix is 3 blocks long.

In the context of this thread, the important classes are as follows:

  1. Global Unicast Addresses (GUA) - Fully route-able public/registered addresses. Valid anywhere.
    The first block of the prefix must be in the range of 2000 to 3fff (although I don't think any have yet been allocated in the 3xxx range). Supplied from upstream, no local control, can (and often does) change at the whim of the ISP.
  2. Unique Local Unicast (ULA) - Locally route-able unregistered private addresses. Valid on locally routed networks (eg corporate sites linked by private backhaul). Should be blocked from the Internet by ISPs, but if not, it does not matter because there are no routes for this class of unregistered addresses in the Internet backhaul. Generated locally so is fully controllable and persistent.
    The first block of the prefix must be in the range of fc00 to fdff.
  3. Link Local Unicast (LLA) - Non route-able local address, always associated with a network interface on the host. Reserved for host to host communications on the same layer 2 local area network. Often blocked by layer 3 user-applications eg browsers. Auto generated by the host.

So for you to get a reliable static address for your in house local servers, ULA is the way forward.

An aside -DHCP vs SLAAC:
In the context of an ipv6 network, the intention is for SLAAC to provide the actual addresses for hosts and DHCP to provide a means of distributing networking parameters/options.
But, confusingly, DHCP6 can also distribute ip addresses, resulting in the duplication usually seen.
Potential problems with this in hosts are mitigated by ignoring the DHCP6 provided address (Android being the strictest)

The host generates it based on what the router advertises.

The router has the following config options:

  1. network.globals.ula_prefix (full three blocks of four hex digits as described above. This is generated randomly on first boot, but can also be set to specific values.
  2. network.lan.ip6hint. This is a fourth block of four hex digits. This is the sub-prefix (or ipv6 ULA subnet). Defaults to 0000 and auto increments by one for each configured "lan" if not specified.

The router periodically sends Router Announcements (RA) to inform hosts of the prefix and sub-prefix.
Hosts can also send Router Solicitations (RS), so they don't have to wait for the next RA to come from the router.

Once the host has the ULA prefix/sub-prefix, it then uses its own unique mac address to generate the full ULA.

Real Example (my test current test system):
ULA prefix fd46:cfe5:34c5::/48
ULA sub-prefix (the ip6hint) ddd6
Host mac address 94:83:c4:20:c7:1d

This results in a stable ULA of fd46:cfe5:34c5:ddd6:9483:c4ff:fe20:c71d/64

Here, the first four blocks fd46:cfe5:34c5:ddd6 represent the prefix/sub-prefix part of the address.
The fifth block is the first two octets of the mac address '9483'
The sixth block is the third octet of the mac plus the hex digits ff, giving c4ff
The seventh block is the hex digits fe, plus the fourth octet of the mac address, giving fe20
The eighth block is the last two octets of the mac address.

This will be stable and fixed and can be used by any application (such as browsers, wget, curl etc). In addition, if you know the host mac address, you can work out the host ULA yourself.

It is not the whole story as there are more nuances, but this always applies.
I hope this helps with your problem.