How to avoid exposing my MAC address when using IPv6?
On my Macs, each IPv6 address includes the MAC address of a specific computer (not of my router). Sites such as ipv6-test.com not only show it, but even tell me it belongs to an Apple computer.
This feels like a super cookie, and might apply to other operating systems as well. How can I avoid my MAC addresses from being exposed?
Background: the MAC address is not in plain sight. Like for 2001:0db8:1:2:60:8ff:fe52:f9d8
:
- Take the last 64 bits (the host identifier) and add leading zeroes:
0060:08ff:fe52:f9d8
. - Strip the
ff:fe
part from the middle. If these bytes are not there, then there's no MAC address. - For the first byte: complement the second low-order bit (the universal/local bit; if the bit is a 1, make it 0, and if it is a 0, make it 1). So:
0x00
(00000000) becomes0x02
(00000010). - Presto:
60:8ff:fe52:f9d8
translates back to MAC address02:60:08:52:f9:d8
.
Note: since macOS 10.12 Sierra, according to Ars Technica Apple has adopted a new way of generating stable addresses that are not based on a MAC address, which Windows apparently had already been doing for years.
This question was a Super User Question of the Week.
Read the blog entry for more details or contribute to the blog yourself
This is solved by two extensions to IPv6:
- RFC 4941 aka "Privacy Addressing" lets outbound connections use temporary, randomly generated addresses (which are rotated every few hours).
- RFC 7217 allows the primary, static address to be generated from an opaque hash which does not reveal any information.
At least one but increasingly both methods are supported by popular operating systems.
Note that these features are orthogonal. You can use both at the same time, if you want to.
Stable private addresses
In some operating systems, the primary interface identifier is no longer generated from MAC or EUI-64 – instead it is generated using a hash or random seed (usually according to RFC 7217)
This kind of address is still static per network – the same OS on the same machine within the same IPv6 prefix should always generate the same suffix. It is suitable for incoming connections.
-
Windows beginning with Windows Vista uses a custom scheme.
To check if the feature is active, run a PowerShell command:
Get-NetIPv6Protocol | fl RandomizeIdentifiers
To enable/disable the feature:
Set-NetIPv6Protocol -RandomizeIdentifiers Enabled
Set-NetIPv6Protocol -RandomizeIdentifiers Disabled
This can also be done using
netsh interface ipv6
. -
NetworkManager on Linux supports RFC 7217 starting with NM v1.2.0, using the connection profile's UUID as part of the seed. This feature is active by default in recent NM versions.
To enable or disable this feature:
nmcli con modify "<profilename>" ipv6.addr-gen-mode stable-privacy
nmcli con modify "<profilename>" ipv6.addr-gen-mode eui64
-
systemd-networkd kind of supports RFC 7217 using this .network file option, but appears to require you to explicitly list network prefixes for which this mode should be used:
[Network] IPv6Token=prefixstable:2001:db8:abcd:123::/64
If no prefixes match, it will still fall back to EUI-64 method.
-
dhcpcd on Linux/BSD supports RFC 7217 using this option in /etc/dhcpcd.conf:
slaac private
To disable this feature and use traditional EUI-64 identifiers:
slaac hwaddr
-
Linux kernel SLAAC supports RFC 7217 as of Linux v4.1.0; however, it must be manually activated by storing the secret seed via sysctl.
The secret key is a 128-bit hexadecimal string (shaped like an IPv6 address), which you can generate using:
uuidgen | sed "s/-//g; s/..../:&/g; s/^://"
This secret key must be stored in the
net.ipv6.conf.default.stable_secret
sysctl. To make it persistent, it could be put in/etc/sysctl.d/50-rfc7217.conf
or similar file:net.ipv6.conf.default.stable_secret = 84a0:d5aa:52b0:4d35:k567:3aa6:7af5:474c
Setting the secret automatically activates this mode for all network interfaces. To check whether the feature is active, look for "addrgenmode stable_secret" in
ip -d link
, or the value "2" insysctl net.ipv6.conf.<ifname>.addr_gen_mode
.
Temporary private addresses
This feature (defined in RFC 4941) provides additional addresses which are generated randomly and rotated every few hours. These addresses are used for outgoing connections only – you still retain your MAC-based or RFC7217-based primary address for incoming connections.
-
Windows supports temporary addresses as of Windows XP SP2.
To enable/disable this feature:
netsh interface ipv6 set privacy state=enabled netsh interface ipv6 set privacy state=disabled
Note that Windows now supports hash-based primary address generation starting with Vista, so this feature isn't as critical.
-
NetworkManager on Linux: Recent versions of NetworkManager handle RA on their own, although the two values below have identical meanings to sysctl (2 = prefer privacy address, 1 = prefer main address):
nmcli con modify <name> ipv6.ip6-privacy 2
Note that NetworkManager now supports RFC7217-based primary address generation starting with v1.2.0, so this feature isn't as important.
Side note: As of 1.4.0, NM allows randomizing the MAC address itself, too. Set
wifi.cloned-mac-address
tostable
to have a different MAC for every network (recommended), orrandom
to randomize it for every connection (may cause problems).In all cases,
<name>
must be the connection name, e.g. WiFi SSID or"Wired Connection 1"
. Usenmcli con
to list all.To make this the default for new connections, as of 1.2.0 you can change
/etc/NetworkManager/NetworkManager.conf
:[connection] ipv6.addr-gen-mode=stable-privacy wifi.cloned-mac-address=stable
-
dhcpcd supports temporary address using the
slaac ... temporary
sub-option:slaac private temporary
or
slaac hwaddr temporary
-
Linux kernel SLAAC supports temporary addresses, but does not use them by default. They can be activated by setting these sysctls:
sysctl net.ipv6.conf.all.use_tempaddr=2 sysctl net.ipv6.conf.default.use_tempaddr=2
The
all
ordefault
part can be replaced with a specific interface name; e.g.net.ipv6.conf.eth0.use_tempaddr
.(I used
ip link set eth0 down && ip link set eth0 up
to force an address assignment, but you can also runrdisc6 eth0
or just wait a few minutes for the next periodic Router Advertisement.) -
Mac OS X – enabled by default since OS X 10.7 Lion:
sysctl -w net.inet6.ip6.use_tempaddr=1
Temporary addresses, if enabled, will be preferred.
-
FreeBSD:
sysctl net.inet6.ip6.use_tempaddr=1 sysctl net.inet6.ip6.prefer_tempaddr=1
-
Older NetBSD versions:
sysctl -w net.inet6.ip6.use_tempaddr=1
Latest NetBSD appears to no longer have kernel SLAAC support, in which case follow dhcpcd instructions instead.
-
OpenBSD – support added in 5.2; enabled and preferred by default in 5.3.
ifconfig em0 autoconfprivacy
ifconfig
shows "autoconfprivacy" next to temporary addresses.
Notes on configuration:
-
On Linux, OS X, and all BSDs, edit
/etc/sysctl.conf
to make the setting permanent. -
On Windows, the changes will persist automatically. (You can append
store=active
to thenetsh
command if you want it to only last until reboot.)
Partially based on IPv6 Operating Systems at IPv6INT.net. See also General IPv6 Notes
If the hardware address is used in the IPv6 address, it usually means your network uses IPv6 Stateless Autoconfiguration. In such case, you can simply pick your own address suffix and configure IPv6 manually.
However, even though the manually added address will not have your hardware info, it will still be static (unlike with Privacy Addressing, which changes addresses every so often). Also, static addresses can be a pain in a network larger than 2-3 devices.
FYI, this only applies to certain IP addressing schemes. More than likely you (or your ISP) are using IPv6 autoconfiguration, which requires a fairly large block of IPs to accomplish in the first place. The solution could be to turn this feature off. Your ISP might use DHCP to assign addresses as well, which is still possible with IPv6.