“Okay, let’s see whether we can reach your Macbook externally via IPv6. What’s the address?”
Sure, let’s have a look.
$ ifconfig ... inet6 2a03:2260:a:b:8aa:22bf:7190:ef36 prefixlen 64 autoconf secured inet6 2a03:2260:a:b:b962:5127:c7ec:d2df prefixlen 64 autoconf temporary ...
Everybody knows that one of these is a random IP address according to RFC 4941: Privacy Extensions for Stateless Address Autoconfiguration in IPv6 that changes once in a while so external observers (e.g. accessed web servers) can’t keep track of my hardware’s ethernet MAC address. This is the one we do NOT want if we want to access the Macbook from the internet. We want the stable one, the one that has the MAC address encoded within, the one with the ff:fe in the middle, as we all learned in IPv6 101.
It turns out, all of my devices that configure themselves via SLAAC, namely a Macbook, an iPhone, an iPad, a Linux laptop and a Windows 10 workstation, don’t have ff:fe addresses. Damn, I have SAGE status at he.net, I must figure out what’s going on here!
After a bit of research totally from scratch with the most adventurous search terms, it turns out that these ff:fe, or more professionally, EUI-64 addresses, have become a lot less common than 90% of IPv6 how-to documents and privacy sceptics want us to believe. On most platforms, they have been replaced by Cryptographically Generated Addresses (CGAs), as described in RFC 3972. The RFC is a close relative to RFC 3971, which describes a Secure Neighbor Discovery Protocol (SeND). Together, they describe a cryptographically secure, PKI-based method of IPv6 address generation. However, as of this writing, only a PKI-less stub implementation of RFC 3972 seems to have become commonplace.
Those CGAs, or as some platforms seem to call them, Privacy Stable Addresses, are generated once during the first startup of the system. The address itself, or the seed used to randomize it, may be (and usually is) persistently stored on the system, so the system will come up every time with this same IPv6 address instead of one following the well-known ff:fe pattern.
To stick with the excerpt from my macOS ifconfig output above, the address marked temporary is a Privacy Extension address (RFC 4941), while the one marked secure is the CGA (RFC 3972).
It’s surprisingly hard to come up with discussions on the web where those two types aren’t constantly confused, used synonymously, or treated like ones that both need to be exterminated, no matter the cost. This mailing list thread actually is one of the most useful resources on them.
This blog post is a decent analysis on the behaviour on macOS, although it’s advised to ignore the comments.
This one about the situation on Windows suffers from a bit of confusion, but is where I found a few helpful Windows commands.
The nicest resource about the situation on Linux is this german Ubuntuwiki entry, which, given a bit of creativity, may provide a few hints also to non-german speakers.
So, how to configure this?
- The related sysctl is net.inet6.send.opmode.
- Default is 1 (on).
- Note how this is the only one that refers to SeND in its name.
- netsh interface ipv6 set global randomizeidentifiers=enabled store=persistent
- netsh interface ipv6 set global randomizeidentifiers=disabled store=persistent
- Default seems to be enabled.
- Use store=active and marvel at how Windows instantly(!) replaces the address.
- It’s complicated.
- NetworkManager defaults to using addr-gen-mode=stable-privacy in the [ipv6] section of /etc/NetworkManager/system-connections/<Connection>.
- The kernel itself generates a CGA if addrgenmode for the interface is set to none and /proc/sys/net/ipv6/conf/<interface>/stable_secret gets written to.
- NetworkManager and/or systemd-networkd take care of this. I have no actual idea.
- In manual configuration, CGA can be configured by using ip link set addrgenmode none dev <interface> and writing the stable_secret in a pre-up action. (See the Ubuntu page linked above for an example.)
- FreeBSD has no support for CGAs, other than a user-space implementation through the package “send”, which I had no success configuring.
So far, I haven’t been able to tell where macOS, Windows and NetworkManager persistently store their seeds for CGA generation. But the next time someone goes looking for an ff:fe address, I’ll know why it can’t be found.