WiFi network not accessible with modified MAC address I've recently bought a Nexus 7 to use as a demo client for a system I am currently developing. For the time being, the system requires the client to have a particular MAC address in order to work. I've rooted the Nexus (still with the Android 4.4 stock ROM), and am using ip link to change the hardware address of wlan0. I am aware that this will be reset on reboot, but as I'd rather not recompile my Android kernel right now, that's okay.

The issue I am seeing is that I am unable to get an IP address from my (open) WiFi network with a modified MAC address. If I set a static IP, I can connect successfully with the modified address, but no packets are getting through.

Hopefully the below transcript will shed some light on exactly what isn't working and what I've tried.

First, I "forget" my WiFi connection and reboot my device just to start from scratch. Then:

$ adb shell
shell@flo:/ $ su
root@flo:/ # ip link | grep -A1 wlan0
22: wlan0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP mode DORMANT qlen 100
    link/ether ac:22:0b:9f:37:f7 brd ff:ff:ff:ff:ff:ff
root@flo:/ # ip link set dev wlan0 addr ac:22:0b:9f:37:f0


Here, I connect to the wireless network. If DHCP is selected, I am simply shown "Obtaining IP address" until the connection fails. If I set a static IP, the network is shown as connected, but:

root@flo:/ # ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
From 192.168.1.113: icmp_seq=1 Destination Host Unreachable
From 192.168.1.113: icmp_seq=2 Destination Host Unreachable
^C
--- 192.168.1.1 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1004ms
pipe 2
1|root@flo:/ # ip route
default via 192.168.1.1 dev wlan0 
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.113 
192.168.1.1 dev wlan0  scope link 
1|root@flo:/ # ip n
192.168.1.1 dev wlan0  INCOMPLETE
255|root@flo:/ # ip n change 192.168.1.1 lladdr 10:0D:7F:4D:1C:D0 dev wlan0
root@flo:/ # ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
^C
--- 192.168.1.1 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6006ms


So, still no connection.
Let's see what happens if I change my MAC address back to the real one without even disconnecting from the wireless network:

root@flo:/ # ip link set dev wlan0 addr ac:22:0b:9f:37:f7
root@flo:/ # ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=13.0 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=9.82 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=9.49 ms
^C
--- 192.168.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 9.491/10.793/13.061/1.609 ms


Does anyone have any idea what might be going on here?

For what it's worth, I am running DD-WRT on my router, no MAC filtering is enabled, and there should be no other "weird" rules set.

UPDATE:
After some further investigation, I have noticed that it seems like the Nexus 7 isn't using the spoofed address at all when talking to my AP. I have enabled MAC filtering and only allowed the spoofed address, and then adb logcat shows a CTRL-EVENT-ASSOC-REJECT message. I'm wondering whether this might somehow be related to this wpa_supplicant question, but there weren't any answers to be had there either...
After much searching, I came across this thread on the xda-developers forum where people seem to be having much of the same issue with a Nexus 4. After trying several of the proposed solutions in that thread, I came across one that worked!

It turns out that Android keeps a permanent record of the MAC in /persist/wifi/.macaddr. For some reason, it insists on using the MAC in that file whenever connecting to a wireless network. If you're on a rooted device, however, you can overwrite it with whatever MAC you want. Interestingly, this change will also persist across reboots!

So, without further ado, here's how you change the MAC permanently on an Android device (substitute 112233445566 with the MAC you want):

computer $ adb shell
android $ su
android # cd /persist/wifi
android # echo -n "112233445566" &gt; .macaddr
android # ^D
android $ ^D
computer $ adb reboot