MAC randomization experiments

331 views
Skip to first unread message

cprise

unread,
Jul 9, 2014, 8:36:35 AM7/9/14
to qubes...@googlegroups.com
As a follow-up to the 'random MAC addresses (wifi)' thread, I was
wondering if anyone has tried automating it on Qubes and if so, what
some of your experiences are.

I have started trying out different approaches, but it appears that the
hooks/interfaces needed at this level are undergoing a great deal of
flux, and the fact of having wifi live in a vm throws a wrinkle or two
in there as well.

My underlying rule is: Since bootup /and/ resume both reset the address
to the hardware ID, randomization must be handled during those events to
prevent the wifi interface from becoming active with and broadcasting
the hardware ID. Handling the bootup part is easy; Suspend is a whole
other story.

I tried adding a script to /etc/NetworkManager/dispatcher.d in the
template used by netvm but this doesn't work in most cases, probably
because there is no "pre-up" --it is all "post". NM people decided in
their infamous wisdom not to follow the ifup/ifdown scripting model...
http://thread.gmane.org/gmane.linux.network.networkmanager.devel/13766/focus=13846

Its very typical of Gnome/RedHat thinking, IMO. Heaven forbid a distro
maintainer write a bad pre-up script and then blame the result on
upstream. Actually, I think they get more blame /this/ way.

Anyway, dispatcher.d isn't triggered by entering sleep on our beloved
Qubes, though the contents of 'qubes-suspend.service' and
'51qubes-suspend-netvm' indicate it is trying to do /something/ about
networking interfaces. The question is, what? The vms don't support
normal suspend/resume processes themselves, so I don't know that these
RPC calls imply.

The score:
* sleep.d broken, pieces of it still used by Qubes systemd config
* dispatcher.d doesn't handle pre-up, so it can't change the MAC address
(iface is already up by the time the script runs)
* Need to find the right place to tell netvm to run macchanger and
nmcli, but I just found the Qubes suspend-netvm hooks and feel a little
confused.

BM-2cTjsegDfZQNGQW...@bitmessage.ch

unread,
Jul 9, 2014, 9:57:59 AM7/9/14
to qubes...@googlegroups.com
> --
> You received this message because you are subscribed to the Google
> Groups "qubes-users" group. To unsubscribe from this group and stop
> receiving emails from it, send an email to
> qubes-users...@googlegroups.com. To post to this group, send
> email to qubes...@googlegroups.com. Visit this group at
> http://groups.google.com/group/qubes-users. For more options, visit
> https://groups.google.com/d/optout.



As a novice attempt, with the goal of a random MAC on every boot, I
tried putting the following script in /rw/config/rc.local, but it did
not immediately work. I tried it with and without bringing the
interface up and down.

#!/bin/sh
ifconfig wlan0 down #this line is optional, depending on where script is
sleep 5 # ifconfig takes a second sometimes
/usr/bin/macchanger -e wlan0 #change only vendor bits
sleep 5
ifconfig wlan0 up

The macchanger program did effective change the mac in the NetVM after
boot, when executed manually.

Andrew B

unread,
Jul 9, 2014, 12:20:00 PM7/9/14
to qubes...@googlegroups.com
On 07/09/14 14:36, cprise wrote:
> As a follow-up to the 'random MAC addresses (wifi)' thread, I was wondering if anyone has tried automating it on Qubes and if so, what some of your experiences are.

I have automated it.

> I have started trying out different approaches, but it appears that the hooks/interfaces needed at this level are undergoing a great deal of flux, and the fact of having wifi live in a vm throws a wrinkle or two in there as well.
>
> My underlying rule is: Since bootup /and/ resume both reset the address to the hardware ID, randomization must be handled during those events to prevent the wifi interface from becoming active with and broadcasting the hardware ID. Handling the bootup part is easy; Suspend is a whole other story.

My approach keeps the random MAC (it does not assign a new MAC, though) after sleep/resume (see below).

> I tried adding a script to /etc/NetworkManager/dispatcher.d in the template used by netvm but this doesn't work in most cases, probably because there is no "pre-up" --it is all "post". NM people decided in their infamous wisdom not to follow the ifup/ifdown scripting model... http://thread.gmane.org/gmane.linux.network.networkmanager.devel/13766/focus=13846
>
> Its very typical of Gnome/RedHat thinking, IMO. Heaven forbid a distro maintainer write a bad pre-up script and then blame the result on upstream. Actually, I think they get more blame /this/ way.
>
> Anyway, dispatcher.d isn't triggered by entering sleep on our beloved Qubes, though the contents of 'qubes-suspend.service' and '51qubes-suspend-netvm' indicate it is trying to do /something/ about networking interfaces. The question is, what? The vms don't support normal suspend/resume processes themselves, so I don't know that these RPC calls imply.
>
> The score:
> * sleep.d broken, pieces of it still used by Qubes systemd config
> * dispatcher.d doesn't handle pre-up, so it can't change the MAC address (iface is already up by the time the script runs)
> * Need to find the right place to tell netvm to run macchanger and nmcli, but I just found the Qubes suspend-netvm hooks and feel a little confused.
>

My approach is not general, but "works for me". It's a two-part combination of 1) a udev rule, and 2) a script that invokes the macchanger utility.
Adding the following udev rule to the netvm template should work for any Intel WiFi card, and should randomize the MAC before any broadcasts are sent (at least, it runs before NetworkManager starts, and you'll be notified if this is not the case).

/etc/udev/rules.d/51-macchanger.rules:
#---begin
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="iwlwifi", RUN+="/home/user/change-mac.sh wlp0s1"
#---end
(replace wlp0s1 with your card's name; this changes depending on device assignments).

and place the randomization script below in the netvm user's home directory (replace the hwaddr with your static MAC [optional], and pick one of the three macchanger options [or use your own]):
/home/user/change-mac.sh:
#---begin
#!/bin/bash
hwaddr="XX:XX:XX:XX:XX:XX"
iface=$1

(
if [ "$#" != "1" ]
then
echo "mac changer script must be given iface name as argument: $@"
echo "Using default of wlp0s1 instead."
iface="wlp0s1"
fi

IFCONFIG="/usr/sbin/ifconfig"
MACCHANGER="/bin/macchanger"
GREP="/bin/grep"
PS="/bin/ps"

nmisrunning=$($PS auxw | $GREP "NetworkManager" | $GREP -v "grep")

$IFCONFIG $iface down
#pick one of the below macchanger options:
#$MACCHANGER -a $iface #change to another WiFi card
#$MACCHANGER -A $iface #change to any valid MAC address
#$MACCHANGER -r -b $iface #change to any random MAC address
$IFCONFIG $iface up

stillthere=$($IFCONFIG | $GREP "$hwaddr")

if [ "$stillthere" != "" ]
then
$IFCONFIG $iface down
echo "macchanger: Hardware WLAN MAC still in use. I took down $iface to (hopefully) prevent infoleaks, but you never know..."
else
echo "macchanger: Changed the WLAN MAC."
fi

if [ "$nmisrunning" != "" ]
then
echo "macchanger: NetworkManager was already running when we started--infoleak possible."
fi
) >/var/log/macchanger_log
#---end

Andrew
0xB364F63E.asc
signature.asc

cprise

unread,
Jul 10, 2014, 1:57:10 AM7/10/14
to Andrew B, qubes...@googlegroups.com
Thanks, Adrew. I did try this and could not get it to work, however. The
udev rule is not triggering at all, and the log file is not created. I
did make the script file executable. I also tried changing the rule to
execute a touch command instead, to see if it would create a file (no
result). The wifi card is an Intel 6300 Ultimate-N using the iwlwifi driver.


Andrew B

unread,
Jul 10, 2014, 6:02:41 AM7/10/14
to cprise, qubes...@googlegroups.com
Well, like I said, this isn't general and just "works for me". I would expect it to work given you have an Intel WiFi card, though.

It seems clear the udev rule isn't being triggered. First, make sure you can manually run the script and it works. Then look at your WiFi card's uevent file (in the /sys tree--mine is at /sys/devices/pci-0/pci0000\:00/0000\:00\:01.0/uevent) and make sure the driver is indeed iwlwifi. You can try the rule with the only restrictions 'SUBSYSTEM=="net", ACTION=="add"'.

If you still don't get it triggered, see if you can trigger the rule manually. First start one terminal monitoring udev events (`udevadm monitor`), then in another terminal trigger the rule (`sudo udevadm trigger --action=add --property-match="DRIVER=iwlwifi"`). You should _at least_ see the add action appear in the monitor output, and should see the log file appear in /var/log or wherever you put it.

A bit hard to debug remotely, but hopefully this gives you some ideas for fiddling and could help make the rule more general.
Best,
Andrew

PS: You can probably also have the udev rule trigger only for your WiFi device by burned-in MAC, but then all other AppVMs that use the same template would have your burned-in MAC accessible.

0xB364F63E.asc
signature.asc

cprise

unread,
Jul 10, 2014, 11:14:43 AM7/10/14
to Andrew B, qubes...@googlegroups.com
Actually, after I added the full path to the touch command and that
started working. However, the script already had the full path (verified
with cut and paste) and is executable, which still doesn't run.

> If you still don't get it triggered, see if you can trigger the rule manually. First start one terminal monitoring udev events (`udevadm monitor`), then in another terminal trigger the rule (`sudo udevadm trigger --action=add --property-match="DRIVER=iwlwifi"`). You should _at least_ see the add action appear in the monitor output, and should see the log file appear in /var/log or wherever you put it.
>
> A bit hard to debug remotely, but hopefully this gives you some ideas for fiddling and could help make the rule more general.
> Best,
> Andrew
>
> PS: You can probably also have the udev rule trigger only for your WiFi device by burned-in MAC, but then all other AppVMs that use the same template would have your burned-in MAC accessible.

Thanks for the tips.

Frank Schäckermann

unread,
Jul 10, 2014, 11:26:23 AM7/10/14
to qubes...@googlegroups.com
> On 10.07.2014, at 17:14, "cprise cprise-at-gmail.com |Google-Groups/Example Allow|" <7e80b...@sneakemail.com> wrote:
>
>
>> On 07/10/14 06:02, Andrew B wrote:
>>> On 07/10/14 07:57, cprise wrote:
>>>> On 07/09/14 12:19, Andrew B wrote:
>>>>> On 07/09/14 14:36, cprise wrote:
>>>>> As a follow-up to the 'random MAC addresses (wifi)' thread, I was wondering if anyone has tried automating it on Qubes and if so, what some of your experiences are.
>>>> I have automated it.
>>>>
>>>>> I have started trying out different approaches, but it appears that the hooks/interfaces needed at this level are undergoing a great deal of flux, and the fact of having wifi live in a vm throws a wrinkle or two in there as well.
>>>>>
>>>>> My underlying rule is: Since bootup /and/ resume both reset the address to the hardware ID, randomization must be handled during those events to prevent the wifi interface from becoming active with and broadcasting the hardware ID. Handling the bootup part is easy; Suspend is a whole other story.
>>>> My approach keeps the random MAC (it does not assign a new MAC, though) after sleep/resume (see below).
>>>>
>>>>> I tried adding a script to /etc/NetworkManager/dispatcher.d in the template used by netvm but this doesn't work in most cases, probably because there is no "pre-up" --it is all "post". NM people decided in their infamous wisdom not to follow the ifup/ifdown scripting model... http://thread.gmane.org/gmane.linux.network.networkmanager.devel/13766/focus=13846
>>>>>
>>>>> Its very typical of Gnome/RedHat thinking, IMO. Heaven forbid a distro maintainer write a bad pre-up script and then blame the result on upstream.. Actually, I think they get more blame /this/ way.
Have you tried to run the script by calling bash from within the udev rule and supplying the script name as parameter?

Regards, Frank

Andrew B

unread,
Jul 10, 2014, 11:45:23 AM7/10/14
to qubes...@googlegroups.com
Actually, I vaguely remember having difficulties with udev not passing the parameter specified in the udev rule (which is why I added the default device name in the script). See if it works when you remove the device parameter from the RUN+= specification.

And just to make sure: manually running this script (directly, from a terminal) works, right?

Andrew
0xB364F63E.asc
signature.asc

cprise

unread,
Jul 10, 2014, 11:12:13 PM7/10/14
to Andrew B, qubes...@googlegroups.com
Frank, I tried prefixing the script with /bin/bash as you suggested, and
that didn't help.

Andrew, it works from the CLI without showing an error and it changes
the address according to 'ip a'. However that resulted in wifi not
working (the bars are there, but I get "Network unreachable" errors when
I try to access anything); I have to disable and re-enable wifi in NM to
get wifi working again (reverts to hardware addr). Since your script is
using ipconfig--is that even compatible with NM?

I can successfully change the addr and use the net if I disable wifi
from NM first, then do macchanger, then re-enable wifi in NM. The new
addr sticks and traffic goes through it. So I'm thinking of using nmcli
instead of ifconfig.

Further, I was wondering maybe there is a length limit for the udev
command? That might explain the odd behavior you mentioned. However, in
my case I see no evidence of it running in logs, so maybe more than the
parameter is getting chopped off. Also, I did put the script into a
subfolder in the home dir, so that makes the path 8 chars longer.

Andrew B

unread,
Jul 11, 2014, 12:34:31 AM7/11/14
to cprise, qubes...@googlegroups.com
Odd that it borks networking when you run it manually; it doesn't do that for me. Did you disconnect from the network before running the script? And as for compatibility: I haven't had any problems and since the script runs before NM starts on netvm boot, I don't see how it would cause incompatibility. And just to be explicit: NM correctly uses the spoofed MAC address.

> I can successfully change the addr and use the net if I disable wifi from NM first, then do macchanger, then re-enable wifi in NM. The new addr sticks and traffic goes through it. So I'm thinking of using nmcli instead of ifconfig.
I've never used nmcli so I can't speak to how well it would work. But I'm not sure what you mean about disabling WiFi: it should only be necessary to first disconnect from any network, not turn the radio off.

> Further, I was wondering maybe there is a length limit for the udev command? That might explain the odd behavior you mentioned. However, in my case I see no evidence of it running in logs, so maybe more than the parameter is getting chopped off. Also, I did put the script into a subfolder in the home dir, so that makes the path 8 chars longer.
I don't think so; I just tested with a subdirectory "reallyreallyreallylongdir" and it worked.

Try this udev rule file:
---begin
SUBSYSTEM=="pci", ACTION=="add", DRIVER=="iwlwifi", RUN+="/home/user/change-mac.sh wlp0s1"
SUBSYSTEM=="pci", ACTION=="change", DRIVER=="iwlwifi", RUN+="/home/user/change-mac.sh wlp0s1"
---end
(this better reflects the information given by `udevadm info --path=<devpath> --attribute-walk` on my system).

Andrew
0xB364F63E.asc
signature.asc

cprise

unread,
Jul 11, 2014, 5:28:17 PM7/11/14
to Andrew B, qubes...@googlegroups.com

On 07/11/14 00:34, Andrew B wrote:
> On 07/11/14 05:12, cprise wrote:
>> On 07/10/14 11:45, Andrew B wrote:
>>> On 07/10/14 17:26, Frank Schäckermann wrote:
>>>>> On 10.07.2014, at 17:14, "cprise cprise-at-gmail.com |Google-Groups/Example Allow|"<7e80b...@sneakemail.com> wrote:
>>>>>
>>>>>
>>>>>> On 07/10/14 06:02, Andrew B wrote:
>>>>>>> On 07/10/14 07:57, cprise wrote:
>>>>>>>> On 07/09/14 12:19, Andrew B wrote:
>>>>>>>>> On 07/09/14 14:36, cprise wrote:
>>>>>>>>> As a follow-up to the 'random MAC addresses (wifi)' thread, I was wondering if anyone has tried automating it on Qubes and if so, what some of your experiences are.
>>>>>>>> I have automated it.
>>>>>>>>
>>>>>>>>> I have started trying out different approaches, but it appears that the hooks/interfaces needed at this level are undergoing a great deal of flux, and the fact of having wifi live in a vm throws a wrinkle or two in there as well.
>>>>>>>>>
>>>>>>>>> My underlying rule is: Since bootup /and/ resume both reset the address to the hardware ID, randomization must be handled during those events to prevent the wifi interface from becoming active with and broadcasting the hardware ID. Handling the bootup part is easy; Suspend is a whole other story.
>>>>>>>> My approach keeps the random MAC (it does not assign a new MAC, though) after sleep/resume (see below).
>>>>>>>>
>>>>>>>>> I tried adding a script to /etc/NetworkManager/dispatcher.d in the template used by netvm but this doesn't work in most cases, probably because there is no "pre-up" --it is all "post". NM people decided in their infamous wisdom not to follow the ifup/ifdown scripting model...http://thread.gmane.org/gmane.linux.network.networkmanager.devel/13766/focus=13846
If I disable wifi in NM, then run the script, it returns "SIOCSIFFLAGS:
Operation not possible due to RF-kill". I think this is because NM puts
the wifi card into airplane mode when disabling it.

It does make sense that that script would work properly before NM
initializes. The catch is I can't get it to run from udev. Are there any
times other than bootup that the script gets triggered on your system?
If not, then maybe /rw/rc.local is a better way to run it.

>> I can successfully change the addr and use the net if I disable wifi from NM first, then do macchanger, then re-enable wifi in NM. The new addr sticks and traffic goes through it. So I'm thinking of using nmcli instead of ifconfig.
> I've never used nmcli so I can't speak to how well it would work. But I'm not sure what you mean about disabling WiFi: it should only be necessary to first disconnect from any network, not turn the radio off.

If you right-click on the NM icon, it lets you disable / enable
interfaces. And what do you know-- it works when I use disconnect
instead of disable. :)

>> Further, I was wondering maybe there is a length limit for the udev command? That might explain the odd behavior you mentioned. However, in my case I see no evidence of it running in logs, so maybe more than the parameter is getting chopped off. Also, I did put the script into a subfolder in the home dir, so that makes the path 8 chars longer.
> I don't think so; I just tested with a subdirectory "reallyreallyreallylongdir" and it worked.
>
> Try this udev rule file:
> ---begin
> SUBSYSTEM=="pci", ACTION=="add", DRIVER=="iwlwifi", RUN+="/home/user/change-mac.sh wlp0s1"
> SUBSYSTEM=="pci", ACTION=="change", DRIVER=="iwlwifi", RUN+="/home/user/change-mac.sh wlp0s1"
> ---end
> (this better reflects the information given by `udevadm info --path=<devpath> --attribute-walk` on my system).
>
> Andrew

Still doesn't run the script.

Joanna Rutkowska

unread,
Jul 17, 2014, 7:51:37 AM7/17/14
to cprise, qubes...@googlegroups.com
On 07/09/14 14:36, cprise wrote:
> As a follow-up to the 'random MAC addresses (wifi)' thread, I was
> wondering if anyone has tried automating it on Qubes and if so, what
> some of your experiences are.
>
> I have started trying out different approaches, but it appears that the
> hooks/interfaces needed at this level are undergoing a great deal of
> flux, and the fact of having wifi live in a vm throws a wrinkle or two
> in there as well.
>
> My underlying rule is: Since bootup /and/ resume both reset the address
> to the hardware ID, randomization must be handled during those events to
> prevent the wifi interface from becoming active with and broadcasting
> the hardware ID. Handling the bootup part is easy; Suspend is a whole
> other story.
>

The NICs I played with some years ago, specifically Intel AGN WiFi, used
to relay on the driver code to set the MAC address on device
initialization. The code looked more or less like this (quoting from
memory):

my_nc_mac = read_eeprom (eeprom_address_mac);
set_hw_mac_address (my_nic_mac);

This means the h/w itself doesn't know the MAC apriori (i.e it's not
burned into the chip), but expects the driver to tell it what the mac
should be.

Patching the driver code above should be the most sure way to change the
mac address and ensure the NIC never ever use the original mac.

joanna.

signature.asc

timet...@gmail.com

unread,
Aug 22, 2015, 5:25:43 PM8/22/15
to qubes-users, cpr...@gmail.com

I'm bumping this old thread to add:

(1) I can't get this to work on my intel wifi either. This seems very much to be a one-off solution.

(2) Joanna writes, "Patching the driver code above should be the most sure way to change the mac address and ensure the NIC never ever use the original mac."

Yes, that's true but I don't know nor heard of any way to patch driver code on the fly. There are two anonymization reasons to hide real mac address. The first is to not tie the mac address to the real owner--patching drivers solves this issue. The second is to prevent tracking across sessions--for this mac needs to be changed on the fly--that is every time a connection to the internet happens. This latter issues is especially vital if the intruder/attacker can sniff the packets on the LAN.

In essence, mac randomization is a form of stream isolation. For an OS that practices security by isolation it's surprising to me that this isn't built into qubes by default.

Reply all
Reply to author
Forward
0 new messages