MAC Spoofing for AppVM

Hi, my purpose is to randomize the mac address of my appvm at every boot, before qubes-tunnel logs into my VPN server.

I’ve read the documentation and the guide appears to be designed only for sys-net; the approach only covers a method with NetworkManager.

Right now I have tried this with Debian 10 and Fedora 32 (both including minimal versions).

sudo nano /lib/systemd/network/99-default.link

from: MACAddressPolicy=persistent
to:   MACAddressPolicy=random

Unfortunately, there are three problems.

  1. eth0 does not start with boot
  2. If i bring eth0 up with “sudo ifconfig eth0 up” there is no internet access (i.e. Network is unreachable)
  3. I have not sufficient technical knowledge to:
    • verify the mac spoofing is done before any program uses eth0 to transmit data
    • design a fail-safe in case the mac spoofing fails.

Some thoughts:
About the first, I think it could be solved with rc.local but is not pretty.
Regarding the second, maybe its messing something with qubes internal scripts?
On third, maybe somehow use a systemd service that uses “Before=network-pre.target”?

I’d love some pointers and thoughs on the matter.

I think this might be impossible. To clarify the issue, the driver in
sys-net and the VPN+eth0 in sys-vpn represent two different types of
network layer: The VPN is normally at layer 3 (IP) but the MAC address
belongs to the layers below that (ethernet).

So, normally, it is only possible to control the MAC address between
your NIC and your router/access point. When people (re)set or randomize
their MAC address, its almost always intended for the local physical
environment because the device’s MAC address isn’t seen beyond that
(i.e. its not transmitted to the Internet). At least, this holds true
for IPv4.

An exception is when configuring the VPN (i.e. openvpn) with a directive
like “dev tap” or some other way to emulate an ethernet link (i.e.
create a bridge). This requires the server to be configured accordingly
but support for layer 2 bridging is rare among VPN providers.

@tasket
In my experience layer 2 bridging is quite common in enterprise VPN, and
it’s widely available. Even openvpn supports layer 2 bridging, although
I haven’t tried it.

As always, it would be helpful if we knew why op wants to do this,
since the answer to that question will determine the answer. @kpn ?

On face value, I’m not sure what kpn means by “solved with
rc.local but is not pretty” - this is exactly the use case for rc.local,
and it’s an obvious place to put a solution.
I use macchanger instead of a systemd solution, and it works across
templates and appVMs. I cant speak to the proposed solution.

There is a much simpler solution for the case if you want to change MAC
for just one qube.
qubes-prefs supports the mac field. So you can use a simple script to
change MAC and start the qube, using a different MAC address each time.
Check out qvm-prefs <qube> mac
Then use that script to start the qube, from a launcher or menu item.
I don’t know if you want to really want to randomise the MAC or if you
want to select and cycle through different addresses - the script would
be different for these cases.
Also, of course, the answer to where to target with that script will
depend on why @kpn wants to do this.

@tasket
In my experience layer 2 bridging is quite common in enterprise VPN, and
it’s widely available. Even openvpn supports layer 2 bridging, although
I haven’t tried it.

As always, it would be helpful if we knew why op wants to do this,
since the answer to that question will determine the answer. @kpn ?

Exactly.

On face value, I’m not sure what kpn means by “solved with
rc.local but is not pretty” - this is exactly the use case for rc.local,
and it’s an obvious place to put a solution.
I use macchanger instead of a systemd solution, and it works across
templates and appVMs. I cant speak to the proposed solution.

IIRC rc.local is executed after the network is up, i.e. your MAC may be leaked during a short timeframe.

That’s why the Qubes doc uses network manager for hostname randomization instead of rc.local or any other autostart variants.

There is a much simpler solution for the case if you want to change MAC
for just one qube.
qubes-prefs supports the mac field. So you can use a simple script to
change MAC and start the qube, using a different MAC address each time.
Check out qvm-prefs <qube> mac
Then use that script to start the qube, from a launcher or menu item.
I don’t know if you want to really want to randomise the MAC or if you
want to select and cycle through different addresses - the script would
be different for these cases.
Also, of course, the answer to where to target with that script will
depend on why @kpn wants to do this.

That’s probably the most simple solution.

Thanks for all your answers.

My personal preference is to use system tools for modfying my system; instead of the usual suspects (e.g. macchanger, macchiato, etc). Although if @unman is willing to teach, I am eager to study in-depth his approach.

What is odd, is that I remember to have used the command from above, on both Debian and Fedora running under Qubes 3.2 and it worked! Thus, it surprised me that on Qubes 4 is not working properly, very strange.

Yes, @tasket you are right. However, I intend to use this same trick on other AppVMs that will not be used for a VPN but for running other applications, that unfortunately I am afraid they will log my MAC; IPv6 is also a severe risk for me because of the possibility to calculate my MAC.

I know everybody’s time in here is valuable, so if you know where the answer might lie in regard to my problem executing the command from above, please do point me in the right direction. Thank you for your time and knowledge.

1 Like

Thank you for the clear statement, which I would summarise as follows:

  1. I want a random MAC so that if remote sites are able to log my MAC
    they will not be able to trace it to me.
  2. I am worried that IPv6 will allow remote sites to calculate my MAC.

If you are not able to disable IPv6 (can be done by kernel option),
then I would use qvm-prefs on the target qubes.
Creating a random MAC address is easy - depending on whether you want a
real MAC address, it may be a little more complicated.
Here’s an example:
Intel have (amongst others) a vendor ID of 02:A0:C9

#!/usr/bin/bash
vendor_id="02:A0:C9"
hex="0123456789ABCDEF"
final3=$( for i in {1..6} ; do echo -n ${hex:$(( $RANDOM %16 )):1} ; done | sed -e 's/\(..\)/:\1/g' )
full_mac=$vendorid$final3
echo $full_mac

This should be quite straightforward :
We define the characters we use in “hex”
Then we choose at random from those characters, and we do this 6 times.
The sed statement splits that string of 6 into 3 pairs, separated by “:”
Then we append that to the vendor_id.

So there’s a random MAC - of course, you might want to choose a vendor
string that doesn’t match your NIC.

You could feed this string in to your qvm-prefs every time you start
Qubes, or (if you wanted to change MAC within session), every time you
start a specific qube.

Here’s an important point - if your machine is seized, then it will be
obvious that you are doing this. So although the authorities wont be
able to demonstrate a direct link between MAC address A and the recorded
MAC address, they may be able to create a plausible link between the
script output and the recorded MAC address. This will apply to almost any
step that you take.

1 Like

Qubes always sets the VM MAC address to the same value for a reason, and
that reason is to address the fingerprinting concerns expressed here.

Should this value be leaked via an exploit or a wayward app, I think all
it indicates is that the data came from a Qubes system (any Qubes
system, not a particular system).

True that - but it’s far easier to target the person using
Qubes, than the person using a generic Intel NIC.
Of course, it’s trivial to identify a Qubes VM, but if all that’s
available is a randomised generic MAC, not so.