Go Beyond

Only read if you don't mind being offended.

Assigning random MAC addresses in Linux

I need to update this a bit, it's old. I'm not the best programmer but am getting better.

There are numerous ways a person can be tracked through the mystical world of networking. Networking itself is pretty transparent, but it's the little things you didn't expect your million+ lines of code operating system and applications set to send out. I saw my Dad's iPhone probing directly for SSIDs the other day, rather than doing an anonymous scan. airdump-ng showed my parent's home network as well as an SSID obviously from a bed-and-breakfast in Utopia, Texas. Merely from watching which client MAC scans for what APs, you can profile a person or use it to track them.

Additionally, DHCP clients attempt to reassign previous leases in most cases. They'll also send a hostname, making it even easier to be tracked. Routers generally log the hostname, time, and IP leased. I regrettably use dhcpcd at the moment, and have taken some measures to limit exposure from the client. This includes the following:

[root@blackmesa ~]# cat /etc/dhcpcd.conf | grep -v "^#" | grep .
option domain_name_servers
option interface_mtu
require dhcp_server_identifier
nohook mtu resolv.conf lookup-hostname hostname

There's even a hostname lookup in that list! The only sure way to know is periodically check tcpdump on your interface with -s0 and maybe -A for simple viewing. It's scary all that is sent out, even though chances of it actually being a problem are generally slim.

My version of dhcpcd is crafty enough to make a /var/lib/dhcpcd directory if one does not exist, which normally contains a lease file per interface. My solution was to touch that path as a file, which cleanly makes it unable to lease and request for re-leases. This may also speed up time to assign an IP, but there's more to be said on that matter and the workings of dhcpcd.

Now, onwards to random MAC addresses. Keeping the above in mind, I don't like to travel around everywhere connecting through public wireless networks using the same MAC address. I periodically change my rc.local to set a different fake MAC address by hand, but would prefer a bit more automation and a less obvious pattern of qwerty-keyboard optimal hex addresses. Ideally, these addresses should use likely and real manufacturer IDs (OUIs) in the first 3 bytes of the MAC address so you don't look unsuspectingly clever to a savvy network admin. I have not yet taken such a precaution.

So, today I probed the Googles for such a utility. Lo and behold, there is one! It's called macchanger, hosted by GNU. Code hasn't been touched since 2004, but I don't think a lot has changed in that front regarding EUI-48 in the past 8 years.

I tried this macchanger utility, man paging it up for its syntax. Pretty simple, lets give it a go:

[root@blackmesa ~]# macchanger -r eth0
Current MAC: 70:00:b5:ac:b0:9b (unknown)
Faked MAC:   16:0b:b8:b8:3f:16 (unknown)
[root@blackmesa ~]# macchanger -r eth0
Current MAC: 16:0b:b8:b8:3f:16 (unknown)
Faked MAC:   9c:a0:e0:44:79:2d (unknown)
[root@blackmesa ~]# macchanger -r eth0
Current MAC: 9c:a0:e0:44:79:2d (unknown)
Faked MAC:   42:ce:2c:26:3a:99 (unknown)
[root@blackmesa ~]# macchanger -r eth0
Current MAC: 42:ce:2c:26:3a:99 (unknown)
Faked MAC:   1a:1e:b9:99:1f:56 (unknown)
[root@blackmesa ~]# macchanger -r eth0
Current MAC: 1a:1e:b9:99:1f:56 (unknown)
Faked MAC:   1a:1e:b9:99:1f:56 (unknown)
It's the same MAC!!

What in the world??? I tried more, and sure enough, the pattern repeated. Its random MAC generator would create the same MAC as prior. With 48 bits to work with, I'm pretty sure something is up.

strace didn't show anything obvious (not that it should), so I had to dive into the code. A few minutes later, a culprit was found:

[root@IcadyptesWannabe macchanger-1.5.0]# grep mc_mac_random src/mac.h
void    mc_mac_random      (mac_t *, unsigned char last_n_bytes);

That's literally the extent of the randomness. I don't know all of the exact specifics, but its widely known that on most architectures in a C environment, initializing variables causes them to come up with "random" data. Of course as this shows, repeating data of unassigned variables is very common. It may even be possible to use this as some sort of data for particular exploits by looking at a client who you know is using this technique.

I am a terrible, terrible programmer. So it really amazes me to see code worse than my own. Under all cases, unless stated otherwise, "random" should mean marginally random. Collisions within 5 attempts is not acceptable. I know perfect random is pretty tricky in technical terms, but /dev/urandom is good enough for me even on days when I'm wearing a tinfoil hat.

So, my solution is a bit different. Write a simple bash/shell script that spits out 6 bytes divided every 8 bits with semicolons, represented as hex. Then use iproute2 to set such a mac (or perhaps macchanger could be used, or ifconfig).

First attempt looked like this. I had to search for a hexdump format howto to figure out the syntax and printf formatting properly, but it made sense after that.

hexdump -e '1/1 "%02X" ":"' /dev/urandom -n 6 | head -c 17

Inexplicably, every 100 tries or so this prints an asterisk character, newline, and then the rest of the sequence. I have not figured out why. Next code looks like this and I'm not sure how portable it is between hexdump implementations:

[root@blackmesa ~]# head -c 6 /dev/urandom | hexdump -C | head -n 1 | cut -d  \
' ' -f 3-8 | tr ' ' ':'

I know this is ugly, but it is a tad bit nifty. I noticed failures every so often setting eth0's MAC with it. Actually, quite frequently. Sometimes 5 failures until a success. Retrying by hand with the problem MAC showed the same failure.

Here's a crazy one:

[root@blackmesa ~]# until ip link set addr `head -c 6 /dev/urandom | hexdump \
-C | head -n 1 | cut -d ' ' -f 3-8 | tr ' ' ':'` dev eth0; do echo -n; done
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
RTNETLINK answers: Cannot assign requested address
(End of output is here, meaning a success)

Alas, this is what I am now using. It's more random than macchanger, and is pretty certain to work (at least, in my environment. No guarantees on yours). I haven't dug into this, but I now think the failures may be related to multi/unicast bits in the OUI portion. The above Wikipedia link should explain that.

So, if you're using macchanger -r/-a/-A expecting random MAC addresses, be aware! Perhaps it works better in environments other than my own, but I do not trust that code at all to provide potential for privacy. They do include a nifty OUI index file with the source tarball, however.

Until next time, Teran/sega01