MAC spoofing: What, why, how, and something about coffee

By on .

MAC spoofing: What, why, how, and something about coffee

MAC addresses are a unique identifier associated to every network interface, wired or wireless. They are used to identify devices on a physical network.

Usually, a network interface comes with a fixed MAC address called the burned-in address. This address cannot be changed, as it is stored in the interface's hardware itself. Because of their fixed nature, they make it pretty easy to use for tracking purposes. This has some some pretty useful applications, such as being used as the matching criterion for a DHCP server to give a static IP address to a given device, or in order to target a "dormant" interface as required for Wake-on-LAN.

MAC spoofing is the technique to effectively change the MAC address that your network interface appears to have. It doesn't change the burned-in address, it merely changes what other devices think your interface's MAC address is. It can be used for some legitimate and not-always-legitimate purposes:

  • Appearing as a legitimate device on a network which employs MAC address whitelisting (useful when your last network interface dies, and for certain types of network attacks)
  • Avoiding tracking: Different MAC addresses means no device on the network can tell if it has already seen this device on this network before, or on another network. For example, Starbucks may wish to maintain a list of all MAC addresses accessing their WiFi access points and use this information to figure out someone's movements or simply to identify who their best customer is (or at least which one is that guy always hogging all the bandwidth). Think they would never do that? Think again.
  • Appearing as a different device to a network you've previously been on. (Hey, remember those "time-limited" free WiFi access points at the airport?)
  • Avoiding profiling: The first three bytes of the MAC address identify the manufacturer of the device. Thus, the burned-in address gives away which company made the chip. Sometimes that's not important, but perhaps a hardware exploit exists in all network interfaces manufactured by $MANUFACTURER, thus changing your MAC address gives you a bit of security by obscurity. Or, more mundanely, perhaps you don't want a thief to be able to see that you have a shiny, new, and very expensive iThingy at your house simply by standing outside and looking all the MAC addresses broadcasted by all your WiFi devices.
  • Bypassing futile roadblocks, and unjustly getting prosecuted to death over it.
  • Wireless access points use MAC spoofing in order to provide multiple wireless networks with a single wireless interface. Recent routers often have this "guest network" feature which, when turned on, makes your router show up twice in the list of available access points: The regular network, and the guest network. This is a good thing, as it gives you some network-level isolation between machines. This way, even if your guests don't practice healthy security practices on their computing devices, at least they won't spread any nasty stuff through your LAN.

Interestingly, while MAC addresses have thus far been limited in terms of tracking potential due to being confined to one's local network, this is about to change with IPv6. One of IPv6's addressing models, stateless address autoconfiguration, allows a device to acquire an address for itself by taking the 64-bit prefix of the network it is on, and using the 48-bit MAC address of its network interface to determine the value of the remaining 64 bits. The consequence of this scheme is that any website you connect to can figure out your MAC address from nothing but your IPv6 address. (More on that later.)

As you can see, there are many reasons as to one would want to spoof their MAC address. So how do we get in on the action?

To randomize MAC addresses, we will be using an aptly-named program called GNU MAC Changer, available on most distributions under the macchanger package. Some distributions have a different package for the Debian version of macchanger, which includes some pretty important fixes such as an updated list of manufacturers, more granularity in the time value used for the random number generator's seed. On Arch, that package is known on the AUR as macchanger-debian. This guide uses the output from the Debian version. There is also a GTK interface to it called macchanger-gtk, but we will not be using this.

Step 1: Preliminary data gathering

In order to spoof a network interface's MAC address, we first need to know which interface we should spoof the MAC address of. Thus, we should check out our list of network interfaces. There are various ways to figure this out (ifconfig, ip, airmon-ng, tab-completion on some commands, etc.). Here, we will use ip because it lists some other information we are interested in:

$ sudo ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet .../xx brd ... scope global eth0
    inet6 .../xx scope link 
       valid_lft forever preferred_lft forever
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
    inet ../xx brd ... scope global tun0
5: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet .../xx brd ... scope global wlan0
    inet6 .../xx scope link 
       valid_lft forever preferred_lft forever

In the above example, 4 interfaces have shown up: lo, eth0, tun0, and wlan0. The output also shows your current MAC address (shown as xx:xx:xx:xx:xx:xx above) and your current IPv4 and IPv6 addresses for each interface. Go through each interface, determine what it's here for, and decide which ones you want to perform MAC spoofing on. In the above example:

  • lo is the local loopback interface. It is used for internal traffic, such as when you run a "local web application" which is simply a process that binds to localhost:someport and lets you connect to it through your browser. This interface has the MAC address 00:00:00:00:00:00 because it is not a real network interface.
  • eth0 is the actual Ethernet network interface of the machine (hence "eth"). You probably do want to spoof the MAC address on this one. Its current MAC address, which should currently correspond to your burned-in address, is shown on the second line ("link/ether xx:xx:xx:xx:xx:xx")
  • tun0 is the virtual interface that would be created by OpenVPN. As it is not a physical network interface, it doesn't have a MAC address.
  • wlan0 is a USB WiFi adapter plugged into the computer. It shows as a physical network interface with its own MAC address. You probably do want to spoof its MAC address: since it's a wireless interface, it will likely travel a lot and connect to a variety of access points, so it is the type of interface that would benefit the most from MAC spoofing.

Other types of interfaces can appear, such as athX (Atheros chips), vboxnetX (virtual network interfaces created by VirtualBox), etc.

Step 1.5 (optional): Renaming network interfaces

If you have a Broadcom chip, read this section. If not, feel free to read it or not. It may prove interesting and/or useful anyway.

Some Broadcom drivers have the very annoying tendency to:

  • Assign a name like ethX to the wireless network interface
  • Inconsistently assign interface names (one boot you have eth0 being the Ethernet interface and eth1 being the wireless interface, the next boot you have eth0 being the wireless interface and eth1 being the Ethernet interface)

This is not only annoying, it also means that if you decide to use MAC spoofing for one of the two interfaces, you may actually be spoofing the MAC address of the wrong interface. This can be fixed by renaming interfaces so that their name stays consistent. And while we're at it, let's not call a wireless interface ethX. To do this, we are going to write udev rules.

First, figure out the MAC address of both interfaces and determines which one belongs to which physical interface.

Then, create a file in /etc/udev/rules.d/ that looks like this:

$ sudo $EDITOR /etc/udev/rules.d/10-network-interface-names.rules
SUBSYSTEM=="net", ATTR{address}=="00:11:22:33:44:55", NAME="wired"
SUBSYSTEM=="net", ATTR{address}=="66:77:88:99:AA:BB", NAME="wifi"

Each line contains the MAC address of the network interface, along with the desired name it should have. This name can be anything descriptive to you, just don't use fancy characters. You will need to reboot for the changes to take place. I suggest you do it now, because the rest of the guide requires you to type the correct network interface names.

Rebooted? Good! Let's continue.

Step 2: Installing the package

This one is a piece of cake. Either install macchanger or the Debian variant of it, using your favorite package manager (in this case, pacman/yaourt).

$ yaourt -S macchanger-debian # Debian version
$ sudo pacman -S macchanger # Non-debian version

Step 3: Initial spoof

We'll assume that the interface you want to perform MAC spoofing on is called wlan0 from this point on. Chances are you are currently still using its burned-in address. Let's check it out:

$ macchanger wlan0
Permanent MAC: 6c:fd:b9:6f:c8:d2 (Proware Technologies Co Ltd.)
Current   MAC: 6c:fd:b9:6f:c8:d2 (Proware Technologies Co Ltd.)

Let's fix that. First, let's bring the interface down so that the network manager doesn't step on our toes (warning: This will disconnect you if you are currently using this interface to access the Internet):

$ sudo ip link set wlan0 down

Now we can ask macchanger to assign a randomized MAC address to the device:

$ sudo macchanger -r wlan0
Permanent MAC: 6c:fd:b9:6f:c8:d2 (Proware Technologies Co Ltd.)
Current   MAC: 6c:fd:b9:6f:c8:d2 (Proware Technologies Co Ltd.)
New       MAC: 3e:72:02:04:0b:3d (unknown)

The output is a bit ambiguous; the "Current MAC" line seems to say that the address is still the same. The actual MAC address of the interface is still the one on the last line, however. You can confirm this by simply running macchanger wlan0 again. Then we can bring the interface back up:

$ sudo ip link set wlan0 up

Now you should be able to use the network interface as normal, with its MAC address spoofed as 3e:72:02:04:0b:3d. But wait! That address is weird. macchanger said it was "unknown", whereas it could determine which manufacturer the original MAC address belonged to. For that, it uses the first 3 bytes of the MAC address, which are attributed to a given organization. For the modest sum of US$1,885 given to the IEEE, you can apply to be given your own 3-bytes sequence (called the Organizationally Unique Identifier, OUI) and proudly appear in the IEEE's public OUI registry. The 3-bytes sequence of the randomized MAC address macchanger chose above, 3e-72-02, is not registered, thus it shows as unknown. This may be good enough (if so, then skip ahead to the next step), but it is a dead giveaway that you are using MAC spoofing to any person or any software watching the MAC address list of the network. This can be used as a criterion for denying you access to the network, for example. To this end, macchanger provides the -A switch, which makes the first 3 bytes be taken from macchanger's internal list of manufacturers. You can view this list using:

$ macchanger -l

The Debian version of macchanger has a much bigger list. Using the -A switch makes it pick the OUI prefix from this list, resulting in a legitimate-looking MAC address:

$ sudo ip link set wlan0 down
$ sudo macchanger -A wlan0
Permanent MAC: 6c:fd:b9:6f:c8:d2 (Proware Technologies Co Ltd.)
Current   MAC: 3e:72:02:04:0b:3d (unknown)
New       MAC: 00:1d:ab:12:84:81 (Swissqual License Ag)
$ sudo ip link set wlan0 up

That's an improvement, but it's still kinda fishy. You can try running the above commands multiple times to cycle through manufacturers and you'll mostly see Chinese companies you've rarely heard of. Thus, a lot of the time, your device will appear to have a MAC address from uncommon manufacturers, by which a human may still deduce that you are spoofing your MAC address. Again, that may be good enough (if so, then skip ahead to the next step). However, we can still do better by reducing the subset of manufacturers macchanger uses to a small list of "known-popular" manufacturers. This way, it becomes harder for others to figure out that the MAC address is spoofed. I have created such a project, affectionately named macchiato (MAC Changer Hiding Identification And Transposing OUIs). There is an Arch package for it that you can install:

$ yaourt -S macchiato-git

Or, if you're on another distribution and you want to install it from scratch:

$ sudo git clone git:// /usr/share/macchiato
$ sudo mkdir /etc/macchiato.d

Now there is some configuration to do. The procedure above (whichever one you used) created a directory called /etc/macchiato.d/. In it, you need to create one configuration file per interface you wish to perform MAC spoofing for. A sample configuration file is provided at /usr/share/macchiato/conf/ It looks like this (the actual file also has in-depth comments):


    00:26:bb # Apple, Inc.

The names in the ouiList entry refer to files in /usr/share/macchiato/oui/ if you installed the Arch package, or /wherever/you/cloned/it/macchiato/oui/ if you cloned it yourself. Each of these files contains a list of common OUI prefixes corresponding to a certain category of network interfaces. For example, wireless_laptop correspond to OUI prefixes of onboard wireless chips found within laptop computers. If you have "common enough" equipment, then feel free to post a comment below listing the OUI prefixes of your network adapters. Make sure to specify which class of network adapter each OUI prefix corresponds to, and the precise model or origin. You can also send a pull request on the macchiato GitHub repository or the Bitbucket one, whichever you prefer.

Create one such configuration file for each network interface (for example, to spoof wlan0's MAC address, create /etc/macchiato.d/

Once all of that is done, run it to see if everything works:

$ sudo /usr/share/macchiato/macchiato /etc/macchiato.d

It will report any error it encounters as it goes along. Once you get everything working, check out if the MAC address has properly changed according to your tastes:

$ macchanger wlan0

All good? Then it's time to...

Step 4: Automatically spoofing the MAC address

If you followed step 3 all the way up to the end and installed macchiato, then you're almost done! You just need to generate the udev rules:

$ sudo /usr/share/macchiato/ /etc/macchiato.d

If you haven't installed macchiato, then things are a bit more difficult. You need to write udev rules to run macchanger as soon as the network interface appears:

$ sudo $EDITOR /etc/udev/rules.d/20-macspoof.rules
ACTION=="add", ATTR{address}=="hardware mac address here", RUN+="/usr/bin/macchanger -A wlan0"
# Need to spoof another interface? Just add another line:
ACTION=="add", ATTR{address}=="hardware mac address here", RUN+="/usr/bin/macchanger -A eth0"

Make sure you put the hardware MAC address of the interfaces there, not the spoofed ones you just generated. These rules will run macchanger as soon as udev notices a new device (ACTION=="add") that has the specified (non-spoofed-yet) MAC address. This includes boot time, of course, but it also includes devices added later, such as USB Wi-Fi adapters.

You're done! You may want to reboot and check macchanger wlan0 once again just to make sure everything works.

Bonus: Enable IPv6 Privacy Extensions

Remember that thing about IPv6 stateless address autoconfiguration from earlier? There exists some (optional) privacy extensions to the scheme, which are enabled by default in some distributions such as Ubuntu, as well as in some other obscure operating systems known by the appealing monikers of "Microsoft Windows" (since Vista) and "OS X" (since 10.7).

An effective way of mitigating the privacy risk of MAC addresses embedded in IPv6 addresses, regardless of whether these privacy extensions are enabled or not, is simply to not use your device's burned-in address: that's MAC spoofing. But while you're at it tweaking your system, you may might as well enable them anyway, right? This is done by setting some kernel parameters. Drop a new file in /etc/sysctl.d/:

$ sudo $EDITOR /etc/sysctl.d/10-ipv6-privacy-extensions.conf
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2

# For each interface, add a line like this:
# net.ipv6.conf.<interface name>.use_tempaddr = 2
# For example:
net.ipv6.conf.eth0.use_tempaddr = 2
net.ipv6.conf.wlan0.use_tempaddr = 2

Minor note: On Ubuntu or Ubuntu-based distributions, a patch has already been applied to your kernel which makes changes to net.ipv6.conf.all.use_tempaddr trickle down to all network interfaces. As such, with those kernels, only the first 2 lines of the above configuration file are necessary. Still, it doesn't hurt to add the rest anyway.

Happy spoofing.

Comments on "MAC spoofing: What, why, how, and something about coffee" (14)

#1 — by

Some real nice editing thar

#2 — by

Once all of that is done, run it to see if everything works:

$ sudo /usr/share/macchiato/macchiato /etc/macchiato.d

It gives back this error

/usr/share/macchiato/macchiato: línea 6: ./ No existe el archivo o el directorio

(The file or directory doesn't exist)

Help, pretty please!

#4 — by

Thanks Etienne

It worked, but in the last step:

brother@DSA-USER ~ $ sudo /usr/share/macchiato/ /etc/macchiato.d
Configuration file '/etc/macchiato.d/' found, but network interface 'wlan0' does not exist.

Currently I have only one usb wireless conected (wlan1), but i will have another one conected (wlan0) (I mean, I will change wireless devices some days, when one of them is very hot - they overheat) So I made two files as you said, and

Anyway, after this warning I tried it. I rebooted, but it didn't change my actual wlan1 mac connected right now.


#5 — by Etienne Perot

Daniel: That's because the message you got is actually an error, not a warning. The script aborted itself because of it, so it didn't write any udev rules, which is why no MAC spoofing occurred.

The reason it considers this message to be an error is because the purpose of this script is to write udev rules for each interface. In order to do that, it needs to find the real (non-spoofed) MAC address of each interface that you have defined macchiato rules for. In order to find those MAC addresses, it requires the network interfaces to exist (at least at the time the script runs).

I have made the script smarter about this, such that it now continues anyway if at least one network interface exists, and the error message is now a lot clearer (it will tell you that MAC spoofing will not be enabled on missing interfaces because it can't find their MAC addresses).

Do a git pull again and re-run the script, and this time it should be able to generate rules for wlan1. If you want MAC spoofing to work on wlan0 as well, you will need to enable that interface so that the script can find wlan0's MAC address. You can disable wlan0 once the script is done running.

#6 — by

First, I have to thank you for taking the time to help me and all your explanations. Everything works great with my wlan1 usb wifi device.

But it doesn't work with my wlan0 device. When I tested sudo /usr/share/macchiato/macchiato /etc/macchiato.d with only wlan0 connected, it said

ERROR: Can't change MAC: interface up or not permission: Invalid argument
[wlan0] WARNING: Failed to assign MAC address '4c:0b:3a:6e:02:55'
[wlan0] Bringing device back up

Anyway, I connected both wlan0 and wlan1 devices to generate the rules for all of them.

I then rebooted, and tried with wlan1 - all worked great

And then again rebooted and tried with wlan0 but as expected from the test, it didn't change the mac. It is a rt2870 usb device, are you aware of some incompatibility with your script?

Thanks again for all your time

#7 — by Etienne Perot

Daniel: There is no chipset-specific code in macchiato, it just calls macchanger or ifconfig or ip link (depending on which is installed on your system) in order to perform the MAC address change. As long as those commands can change your MAC address, then macchiato should work because all it does is call the same thing.

However, some network interfaces don't like having their MAC address changed when they are disabled, and some don't like having their MAC address changed when they are enabled. By default, macchiato will disable the network interface before changing its MAC address, and then enable it again afterwards. You can change this behavior by adding dontBringDown=true to, which will just leave the interface enabled all the time. If you already had dontBringDown=... in, try removing the line completely instead, and see what happens.

If that still doesn't work, check if you can change the MAC address manually, by running either one of the following commands (these are the actual commands macchiato calls to change the MAC address):

$ sudo macchanger -m 00:11:22:33:44:55:66 wlan0
$ sudo ip link set wlan0 address 00:11:22:33:44:55:66
$ sudo ifconfig wlan0 hw ether 00:11:22:33:44:55:66

Try each of those, both when the interface is enabled and disabled. (You can disable an interface by doing ip link set wlan0 down or ifconfig wlan0 down, and enable it by doing the same but with up instead of down.)

If none of those commands work, then macchiato won't work either. It probably means your particular device doesn't allow its MAC address to be changed, in which case your only options are to either accept that, or not to use the device at all :(

If the commands do work, then it's a bug in macchiato. In this case, please do another git pull (I added a MACCHIATO_DEBUG environment variable for debugging) and then run this:

$ sudo MACCHIATO_DEBUG=true /usr/share/macchiato/macchiato /etc/macchiato.d 2>&1 | tee ~/macchiato.log

This will print a lot of lines, which shows exactly what the script is doing, which things it is checking, what commands it is running, etc. Email me the full output (which has already been saved in ~/macchiato.log by the tee command), and I should be able to fix it.

#8 — by

OK I tried this with the same new mac that this device uses in windows (because in Windows I can change its mac)

  • $ sudo macchanger -m 00:11:22:33:44:55:66 wlan0
  • $ sudo ip link set wlan0 address 00:11:22:33:44:55:66
  • $ sudo ifconfig wlan0 hw ether 00:11:22:33:44:55:66

None of them worked (device up and down, none worked). When up, it says that I have to down before. When down it says:

  • ERROR: Can't change MAC: interface up or not permission: Invalid argument
  • RTNETLINK answers: Invalid argument
  • SIOCSIFHWADDR: Invalid argument

Then I tried changing that line in

First to true and rebooted - it didn't change mac

Then removing it completely and rebooted - it didn't change mac

Don't worry, your script and method works great, and your explanations were very detailed to help me know the problem (this device with this driver can't change its mac) I will have to investigate if in another distribution it works, who knows.

Just a last pair of questions, for my other working wifi device:

  • Do I have to put it always in the same USB port for this to work?
  • If I boot linux without the wifi device connected, and then, later I connect it, will it change the mac or is it necessary to always reboot?


#9 — by Etienne Perot

Daniel: As you have guessed, this means that the Linux driver for your device doesn't allow changing the MAC address (whereas the Windows one does). Unfortunately, there's not much you can do about it, other than patching the driver yourself or bugging Realtek about it. Trying other distributions may also help, in case you're using an old distribution with old drivers.

To answer your other questions:

The USB port you put it into doesn't matter. You can check it out by yourself by looking at the rule generated by, it should look like this:

ACTION=="add", ATTR{address}=="00:11:22:33:44:55", RUN+="..."

This means: whenever udev sees a new device (ACTION=="add"), with this MAC address (ATTR{address}=="00:11:22:33:44:55"), then run this command (RUN+="..."). It doesn't depend on which port the device is placed in, it depends on the device's initial MAC address, which is why the script needed to collect it earlier.

The above explanation should answer your second answer as well. Since the macchiato command is run every time a device with this MAC address is plugged in, that means macchiato will run every time you plug the device in (the MAC address of your device will always be the hardware one when it is plugged in; it doesn't "remember" the spoofed MAC address once unplugged). Therefore, you do not need to reboot for MAC spoofing to occur. However, macchiato always picks a random MAC address when it runs; it doesn't remember that it assigned a particular MAC address to a particular device. That means that when you plug the device in, you will get a different MAC address than the one you had the previous time you plugged it in.

Here's a bonus tip: You can add a new udev rule to make it ignore wlan0 completely, that way you don't accidentally use it sometime when you're not paying attention. To do this, create a udev rule that looks like this:

SUBSYSTEM=="net", ATTR{address}=="66:77:88:99:aa:bb", OPTIONS+="ignore_device"

You can do some cool stuff like this with udev, such as blocking known-bad hardware like mouse jigglers. Fun stuff.

#10 — by

OK , I am going to save this whole article in my hard drive, bacause sometimes it happened to me when coming back to a blog it was down or disappeared, and great information was lost!

I will add that rule, thanks again!

#11 — by

About three years ago I became concerned about businesses tracking me whenever I got on line, so I installed no script, and other extensions on Firefox. But I found out I couldn't get on line at many places where you had to click to agree by their terms, so I installed Google Chrome without any extensions, too.

Then at one small cafe, the guy behind the counter, and a friend, cut me off line as a joke by blocking my MAC address. "No problem," I told him, "I'll just change my MAC address." And I did. He blocked the new MAC address, so I wrote a script to change it again.

The script is reproduced here:

#!/bin/bash -x

MAC=00:`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 200 | md5sum | sed -r 's/^(.{10}).*$/\1/;
s/([0-9a-f]{2})/\1:/g; s/:$//;'`;

sudo ifconfig wlan0 down

sudo ifconfig wlan0 hw ether $MAC

sudo ifconfig wlan0 up

sudo service network-manager restart

Yeah, yeah, I know ifconfig is being deprecated......

Anyway, this script worked just fine anywhere for the longest time. That is, until July 13 this year at Panera's. I assume they have some java script that gets the actual MAC address or maybe network manager was updated to allow them to get the actual MAC address. I do not know which scenario is the true one but I suspect it is a script.

Have you encountered anything like this? And is there a way around it?

Update: I am at Panera's right now, and have just observed that the logon procedure does in fact grab the real MAC address. A spoofed MAC address is ignored and somehow still grabs the real MAC address. This occurs despite having cleared out the browser cache using Chrome to clear all data (except bookmarks) and following up by clearing it again using Bleach Bit.

#12 — by Anonymous


#13 — by

A more generic rule to set Mac for all connections?

ACTION=="add", SUBSYSTEM=="net", KERNEL=="*" RUN+="/usr/bin/macchanger -m XX:XX:XX:XX:XX:XX %k"

#14 — by Anonymous

This doesn't work, because systemd-udevd fails on timeout trying to apply this rule, probably because of macchanger, as the example above with exact mac specification works just fine.

Replying to: MAC spoofing: What, why, how, and something about coffee