How to stop MAC address from changing after disconnecting?
I changed my MAC address with macchanger -A wlp68s0b1 at boot with crontab, Here is what happens when I disconnect and reconnect: While connecting after boot:
rahman@debian:~$ macchanger -s wlp68s0b1 Current MAC: 00:22:31:c6:38:45 (SMT&C Co., Ltd.) Permanent MAC: 00:00:00:00:00:00 (FAKE CORPORATION)
rahman@debian:~$ macchanger -s wlp68s0b1 Current MAC: 16:7b:e7:3c:d3:cd (unknown) Permanent MAC: 00:00:00:00:00:00 (FAKE CORPORATION)
rahman@debian:~$ macchanger -s wlp68s0b1 Current MAC: 00:00:00:00:00:00 (FAKE CORPORATION) Permanent MAC: 00:00:00:00:00:00 (FAKE CORPORATION)
And so on. With every disconnect I get a different random MAC address which fades on reconnecting, giving me my real MAC address. What causes that and how to stop it? Some outputs:
rahman@debian:~$ lspci -nn |grep 14e4 44:00.0 Network controller [0280]: Broadcom Limited BCM4313 802.11bgn Wireless Network Adapter [14e4:4727] (rev 01) rahman@debian:~$ uname -a Linux debian 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u5 (2017-09-19) x86_64 GNU/Linux rahman@debian:~$ sudo ifconfig enp0s25: flags=4099 mtu 1500 ether 00:24:c0:7b:a8:8b txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 20 memory 0xd4800000-d4820000 enp0s25:avahi: flags=4099 mtu 1500 inet 169.254.9.109 netmask 255.255.0.0 broadcast 169.254.255.255 ether 00:24:c0:7b:a8:8b txqueuelen 1000 (Ethernet) device interrupt 20 memory 0xd4800000-d4820000 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1 (Local Loopback) RX packets 9436 bytes 6584515 (6.2 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 9436 bytes 6584515 (6.2 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 wlp68s0b1: flags=4163 mtu 1500 inet 192.168.1.5 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::6711:9875:eb78:24fc prefixlen 64 scopeid 0x20 inet6 fd9c:c172:b03b:ce00:f1e0:695e:7da0:91a prefixlen 64 scopeid 0x0 ether 00:00:00:00:00:00 txqueuelen 1000 (Ethernet) RX packets 484346 bytes 641850809 (612.1 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 368394 bytes 44259668 (42.2 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 rahman@debian:~$ sudo iwconfig lo no wireless extensions. enp0s25 no wireless extensions. wlp68s0b1 IEEE 802.11 ESSID:"3bdo" Mode:Managed Frequency:2.447 GHz Access Point: 9C:C1:72:B0:3B:D4 Bit Rate=65 Mb/s Tx-Power=30 dBm Retry short limit:7 RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality=54/70 Signal level=-56 dBm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:4 Invalid misc:183 Missed beacon:0
MAC Address Spoofing in NetworkManager 1.4.0
The new NetworkManager release 1.4.0 adds new features to change the current MAC address of your Ethernet or Wi-Fi card. This is also called MAC address “spoofing” or “cloning”.
Previously NetworkManager 1.2.0 added MAC address randomization for Wi-Fi, as Lubomir explains in his blog post. He also explains why you may want to do that in the first place, so I skip the introduction. Suffice to say, some consider randomizing the MAC address an important feature to protect their privacy. Only be aware that for real™ privacy, more considerations come into play. The Tails distribution and Wikipedia have good reads on the subject.
1.2.0 relies on support from wpa_supplicant to configure a random MAC address. The problem is that it requires API which will only be part of the next major release 2.6 of the supplicant. Such a release does not yet exist to this date and thus virtually nobody is using this feature.
With NetworkManager 1.4.0, changing of the MAC address is done by NetworkManager itself, requiring no support from the supplicant. This allows also for more flexibility to generate “stable” addresses and the “generate-mac-address-mask”. Also, the same options are now available not only for Wi-Fi, but also Ethernet devices.
Tools like macchanger and macchiato are commonly used to change the MAC address of a device. They support flexible mechanisms to generate a random address, most of these options are now also supported by NetworkManager.
Randomization during Wi-Fi scanning
During Wi-Fi scanning, NetworkManager resets the MAC address frequently to a randomly generated address. This was already enabled by default in 1.2.0, but as said, users likely didn’t have the required support from wpa_supplicant.
This default behavior can be disabled with a global configuration option in NetworkManager.conf:
[device] wifi.scan-rand-mac-address=no
Note that this is a per-device configuration value, because at the time of Wi-Fi scanning, no connection is yet activated. A “connection” in NetworkManager-speak is a profile, a bunch of settings.
Supported Modes
Since long, NetworkManager supports two connection properties “ethernet.cloned-mac-address” and “wifi.cloned-mac-address”. These settings take effect when activating the connection. They got extended in 1.4.0 and support the following values:
- An explict MAC address: this was already supported before 1.4.0 and allows to spoof a specific MAC address.
- “permanent”: use the permanent MAC address of the device. Before 1.4.0, the permanent MAC address was used if the “cloned-mac-address” property was left empty, thus it was the default.
- “preserve”: don’t change the MAC address of the device upon activation.
- “random”: generate a randomized value upon each connect.
- “stable”: generate a stable, hashed MAC address.
- NULL/unset: this is the default value which allows fallback to a globally configured default, see below. In case no global override exists, NetworkManager falls back to “permanent”, like it did before.
Update-2017-01-25: with 1.6 release and newer, the default value changed from “permanent” to “preserve” [commit],[bug].
Note that in the D-Bus API, the “cloned-mac-address” field is not a string and thus could not be extended in a backward compatible way. That is why on D-Bus there are new fields “ethernet.assigned-mac-address” and “wifi.assigned-mac-address” instead. On the other hand, in nmcli, libnm.so, and keyfile-format the properties are indeed called “cloned-mac-address”.
How to configure it?
It is likely that your favorite NetworkManager client does not expose these options in the UI. In that case, I would suggest to use nmcli to configure the per-connection settings:
$ nmcli connection show NAME UUID TYPE DEVICE My Wi-Fi fca8fc45-c47. 802-11-wireless -- . $ nmcli connection show "My Wi-Fi" . $ nmcli connection modify "My Wi-Fi" \ wifi.cloned-mac-address stable $ nmcli connection up "My Wi-Fi" $ ip link show .
Stable MAC Address Generation
The “stable” method warrants more explanation. In a way it is similar to “random”, but instead it generates a stable, hashed value. This way every time the connection activates, the same address is generated. However, each connection generates a different address.
This is for example useful so that you get the same IP address from DHCP, which might not be the case with “random”. Or a captive-portal might remember your login-status based on the MAC address. With “random” you may be required to re-authenticate on every connect.
The “stable” mode still makes you easily recognizable when you re-connect to a previous network, but your hardware MAC address is hidden and tracking you across different networks may be harder (YMMV).
The stable address is generated by hashing a private key from /var/lib/NetworkManager/secret_key , the ifname of the device, and a stable-id. The stable-id by default is the UUID of the connection (“connection.uuid”), unless you configure the new property “connection.stable-id“. The latter allows you to have multiple connections that generate the same MAC address. Note that “connection.stable-id” property is also used when generating stable-privacy IPv6 addresses (“ipv6.addr-gen-mode”, RFC 7217).
Format of the MAC Address
The “random” and “stable” modes both generate a MAC address. By default, all 48 bits of the MAC address are scrambled except the following two bits. For one, the LSB of the first octet which must always be cleared to indicate a unicast MAC address. And then, the 2nd-LSB of the first octet is set to indicate a locally administered address — contrary to a burned-in address. This has the same effect as calling macchanger —random with respect to which bits are scrambled.
Which bits are scrambled is configurable by the per-connection properties “ethernet.generate-mac-address-mask” and “wifi.generate-mac-address-mask” [man]. During Wi-Fi scanning, the per-device property “wifi.scan-generate-mac-address-mask” is used instead [man].
The property works as follows. If the mask-setting contains one MAC address, that address is used as a mask. For example “FF:FF:FF:00:00:00” results in randomizing the lower 3 octets and use the vendor OUI of the device’s permanent MAC address. This is similar to macchanger —ending , except that NetworkManager uses the permanent MAC address of the device while macchanger preserves the OUI of the current address.
Update-2016-11-04: it doesn’t use the permanent MAC address, instead the “initial” MAC address, that is the current MAC address that was configured on the device outside of NetworkManager.
If after the initial mask a second MAC address follows, that address is used instead of the device’s permanent address. For example “FF:FF:FF:00:00:00 00:50:E4:00:00:00” sets the OUI to “00:50:E4” but randomizes the last 3 octets. Likewise, “02:00:00:00:00:00 00:00:00:00:00:00” scrambles all bits but clears the second LSB of the first octet, thus creating a burned-in address like macchanger —random —bia .
Actually, there can follow arbitrary many MAC addresses after the mask, in which case one will be chosen randomly. “02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00” will scramble all 47 bits — except the unicast bit which must be always cleared. This allows you to specify a list of OUIs.
Global Default Configuration
NetworkManager supports certain per-connection properties to fallback to a globally configured default value. By having “cloned-mac-address” or “generate-mac-address-mask” unset, it allows fallback to a value configured in NetworkManager.conf.
For example, I have a file /etc/NetworkManager/conf.d/30-mac-randomization.conf like:
[device-mac-randomization] # "yes" is already the default for scanning wifi.scan-rand-mac-address=yes [connection-mac-randomization] ethernet.cloned-mac-address=random wifi.cloned-mac-address=random
which sets the default fallback to random. Only for a few selected connection profiles I explicitly switch the per-connection setting to “stable”.
Note: distributions and packages are advised to install configuration snippets to /usr/lib/NetworkManager/conf.d directory instead of /etc .
What’s missing?
One idea would be to support some special “connection.stable-id”. This would allow to implement a “change daily” feature like Windows 10 has. Allowing for a stable-id “time: ” could have the effect to start at — and generate a new ID each time. Say, “time: 2016-08-22 6:00:00 7d” could mean to generate a new ID every Monday at 6:00 a.m. Of course, the ID only gets re-generated upon activation of a connection.
Update-2017-01-25: since 1.6, NetworkManager supports dynamic stable-ids like «$» , «$» , «$» or any combination of these. This also affects RFC7217 stable privacy IPv4 addresses [commit], [example].
Another idea would be to allow a special keyword “preserve” in “generate-mac-address-mask”. It could be used to set a value like “FF:FF:FF:00:00:00 preserve” which should have the same effect as macchanger —ending and use the current MAC address instead of the permanent one.
If you have problems, questions or suggestions, meet us on mailing list, IRC (#nm on freenode) or check our documentation and our bugtracker.