IPv6 SLAAC Host OS Address Allocation

IPv6 SLAAC Host OS Address Allocation

While rebuilding my v6 lab with a variety different host OS, I found that there is no single approach to address generation in IPv6 SLAAC networks.

I've recorded my findings below for future reference, but also as a good way to delve deeper into the murky world of IPv6 address generation and shine a light on just what is all this stuff in our 'ifconfig/ip add' commands.

TL;DR

The table below summarizes my observations

| OS | Address Generation | Temporary Address |
|--------|---|---|---|---|
| macOS 10.14.6 | Stable-privacy | Yes |
| Ubuntu 18.04 | Stable-privacy | Yes |
| Debian 10 | EUI-64๐Ÿ‘ˆ๐Ÿ‘€ | Yes |
| Fedora 30 | Stable-privacy | No ๐Ÿ‘ˆ๐Ÿ‘€|
| Windows 10 1903 | Randomized IID | Yes |

Lab Setup

I'm running a basic LAN topology with a combination of hardware (Windows 10 and macOS), plus virtual machines for the Linux OS.

  • Virtualization platform: Hyper-V on Windows 2019 Server
  • Host OS:
    • Windows 10 running on an HP Z book.
    • macOS version 10.14.6 running on a MBP 2017
    • Ubuntu 18.04.3
    • Fedora 30
    • Debian 10 Stable
  • Gateway: ArubaOS-Switch 2930F-8G-PoE+-2SFP+ running WC.16.07.0002

Gateway configuration:

ipv6 unicast-routing
vlan 51
   name "VLAN51"
   untagged 1
   tagged 3-4
   ip address 192.168.51.1 255.255.255.0
   ip helper-address 192.168.50.10
   ipv6 address 2001:db8:a:51::1/64
   exit
  • IPv6 is globally enabled.
  • IPv6 and SLAAC are enabled on the VLAN interface by configuring the IPv6 address with a /64 prefix.
  • The gateway will issue a Router Advertisement with the Autonomous Address (A) flag and On-Link (L) flag on for the 2001:db8:a:51::/64 prefix.
  • I also running IPv4 with DHCPv4 to create a dual-stack environment.

Host OS

macOS

macOS allocates a link-local address and two global addresses, 'secured' and 'temporary'. The 'secured' global address is not generated using EUI-64, but appears to be an RFC7217 'stable-privacy' address. The 'temporary' address is a Privacy Extension address.
As a result there is no link between the hardware address of 00:e0:4c:68:00:91 and the IPv6 addresses.

en7: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	options=4<VLAN_MTU>
	ether 00:e0:4c:68:00:91
	inet6 fe80::106e:510e:a06c:8103%en7 prefixlen 64 secured scopeid 0x13
	inet6 2001:db8:a:51:1c6e:af46:a44d:803c prefixlen 64 autoconf secured
	inet6 2001:db8:a:51:fcc5:73cc:9f29:497c prefixlen 64 autoconf temporary
	inet 192.168.51.108 netmask 0xffffff00 broadcast 192.168.51.255
	nd6 options=201<PERFORMNUD,DAD>
	media: autoselect (1000baseT <full-duplex>)
	status: active

Information about macOS CLI commands usually consist of aging blog posts, and v6 info is hard to come by. But I did find the following which sets the temporary address setting:

$ sysctl net.inet6
$ sysctl net.inet6.ip6.use_tempaddr
net.inet6.ip6.use_tempaddr: 1

Linux Host OS

A note about 'nmcli'

I am using the 'ip add' command for an overview of the host addressing and the 'network manager' tool to gather more detailed information.
Details of the latter can be found in the man nm-setting page.
Of interest are the settings for:

  • ipv6.addr-gen-mode - This is the method used to generate the non-temporary address, the one with the longer lifetime, created by SLAAC. The options are NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 or NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY. 'If the property is set to EUI64, the addresses will be generated using the interface tokens derived from hardware address...The value of stable-privacy enables use of cryptographically secure hash of a secret host-specific key along with the connection's stable-id and the network address as specified by RFC7217.' - man page of nm-settings.
  • ip6-privacy - This setting determines whether Privacy Extensions are enabled. If enabled an additional address labeled 'temporary' will be generated. 'If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one...The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses).' - man page of nm-settings. If the setting is 'unknown', 'ipv6.ip6-privacy' is checked, and if that is not configured then /proc/sys/net/ipv6/conf/default/use_tempaddr is used.

The values of these two settings can be seen by using the following command:

nmcli connection show <connecion-name> | grep 'ip6\|gen-'

Ubuntu 18.04

Ubuntu uses a temporary address and 'stable-privacy' rather than EUI-64. Here we see the 2001:db8:a:51:a9d5:d055:bcb8:6081/64 address marked with temporary and with the shorter preferred lifetime than the other global address.

$ ip add show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:30:14:63 brd ff:ff:ff:ff:ff:ff
    inet 192.168.51.107/24 brd 192.168.51.255 scope global dynamic noprefixroute eth0
       valid_lft 679119sec preferred_lft 679119sec
    inet6 2001:db8:a:51:a9d5:d055:bcb8:6081/64 scope global temporary dynamic
       valid_lft 592722sec preferred_lft 74050sec
    inet6 2001:db8:a:51:eaaf:e6bd:c0a1:f4d4/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591610sec preferred_lft 604410sec
    inet6 fe80::9793:53f3:7d4:7ebf/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

nmcli can be used to see the default settings. `

$ nmcli connection show
NAME                UUID                                  TYPE      DEVICE
Wired connection 1  6be33915-6eed-3797-ab04-ad6cbaad8a78  ethernet  eth0
$ nmcli connection show Wired\ connection\ 1 | grep 'ip6\|gen-'
ipv6.ip6-privacy:                       -1 (unknown)
ipv6.addr-gen-mode:                     stable-privacy
$ cat /proc/sys/net/ipv6/conf/default/use_tempaddr
2

Debian 10

Even though Ubuntu is a Debian-based distribution, the default settings between the two OS are different. Debian 10 uses temporary addresses, and this is configured directly as the global 'ipv6.ip6-privacy', but also generates its global address using EUI-64.
Here we can see that the hardware address 00:15:5d:30:14:60 is used to generate the EUI-64 address 2001:db8:a:51:215:5dff:fe30:1460/64

$ ip add show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:30:14:60 brd ff:ff:ff:ff:ff:ff
    inet 192.168.51.102/24 brd 192.168.51.255 scope global dynamic noprefixroute eth0
       valid_lft 679038sec preferred_lft 679038sec
    inet6 2001:db8:a:51:2838:b79f:2498:bb6b/64 scope global temporary dynamic
       valid_lft 592640sec preferred_lft 73875sec
    inet6 2001:db8:a:51:215:5dff:fe30:1460/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591804sec preferred_lft 604604sec
    inet6 fe80::215:5dff:fe30:1460/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

Check nmcli for the default settings.

$ nmcli connection show Wired\ connection\ 1 | grep 'ip6\|gen-'
ipv6.ip6-privacy:                       2 (enabled, prefer temporary IP)
ipv6.addr-gen-mode:                     eui64

Fedora 30

Fedora 30 originates from the Red Hat family of distributions, and exhibits yet another default configuration. The global address uses 'stable-privacy' and no temporary address is enabled by default. This is the only OS I have tested that does not use a temporary address.

$ ip add show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:30:14:5f brd ff:ff:ff:ff:ff:ff
    inet 192.168.51.101/24 brd 192.168.51.255 scope global dynamic noprefixroute eth0
       valid_lft 679510sec preferred_lft 679510sec
    inet6 2001:db8:a:51:46c0:8eb5:d6e8:3469/64 scope global dynamic noprefixroute
       valid_lft 2591964sec preferred_lft 604764sec
    inet6 fe80::277a:e1f7:faf3:d64/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
       
$ nmcli connection show
NAME                UUID                                  TYPE      DEVICE
Wired connection 1  1576c850-3c2a-3172-8342-49a349d174ff  ethernet  eth0

$ nmcli connection show Wired\ connection\ 1 | grep 'ip6\|gen-'
ipv6.ip6-privacy:                       -1 (unknown)
ipv6.addr-gen-mode:                     stable-privacy
$ cat /proc/sys/net/ipv6/conf/default/use_tempaddr
0

Windows 10

By default Windows 10 1903 uses a 'Randomized' global address (non-EUI-64) and a temporary address.

EDIT Sept 2020:
Interestingly, Windows 10 does not use RFC7217 (thanks to Fernando Gont for pointing this out.)
Windows uses a Randomized interface ID but this remains constant across different networks. If one moves a Windows client from one network to the next, only the network ID changes. The host ID, while random, remains the same.

The IPv6 protocol settings can be found by issuing the Powershell command Get-NetIPv6Protocol which I've truncated here with the relevant information.

PS C:\Users\joe> Get-ComputerInfo | ft WindowsVersion, OsBuildNumber

WindowsVersion OsBuildNumber
-------------- -------------
1903           18362

PS C:\Users\joe> get-netipaddress -InterfaceIndex 25 -AddressFamily ipv6


IPAddress         : fe80::1513:3c4b:4770:7cae%25
InterfaceIndex    : 25
InterfaceAlias    : Ethernet
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 64
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Preferred
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : 2001:db8:a:51:f0c9:bef:547a:aa70
InterfaceIndex    : 25
InterfaceAlias    : Ethernet
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 128
PrefixOrigin      : RouterAdvertisement
SuffixOrigin      : Random
AddressState      : Preferred
ValidLifetime     : 6.23:54:45
PreferredLifetime : 23:54:22
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : 2001:db8:a:51:1513:3c4b:4770:7cae
InterfaceIndex    : 25
InterfaceAlias    : Ethernet
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 64
PrefixOrigin      : RouterAdvertisement
SuffixOrigin      : Link
AddressState      : Preferred
ValidLifetime     : 29.23:54:45
PreferredLifetime : 6.23:54:45
SkipAsSource      : False
PolicyStore       : ActiveStore

PS C:\Users\joe> Get-NetIPv6Protocol | ft RandomizeIdentifiers, UseTemporaryAddresses

RandomizeIdentifiers UseTemporaryAddresses
-------------------- ---------------------
             Enabled               Enabled

Summary

  • I seem to be spending a lot of my time with IPv6 just looking at the relationship between the host OS and the Network OS, and especially the address-allocation process.
    The variations in behaviour of the various hosts and the different address allocation methods, such as SLAAC and DHCPv6, create an area of detail not present in IPv4 networks.
  • Network Admins supporting or planning an IPv6 deployment would be wise to take time to investigate IPv6 address allocation and the behaviour of their supported host OS. They should document the expected address allocation methods and align their gateway configuration according.
    In addition, documenting the expected addresses; the number and types of address on a host, will aid with troubleshooting processes. When faced with a large number of addresses and lots of information in a 'ifconfig', or similar command, gleaning information can be difficult for the less-experienced. Simply answering the question 'what is your IP address?' can be a source of confusion.
  • The variations in the defaults provides an interesting point of observation and I think this is note-worthy.

@joeneville_