Can't connect to mullvad vpn (set up as app vm)

Hi everyone
This is actually my second go at doing this. I gave up thinking that last time it may have been the laptop or whatever. But I’m back having another go with another laptop, fresh qubes install.

So I’ve been using this guide by Micah Lee

I have gone over this many times and followed his instructions with a bloody magnifying glass, fine tooth comb etc etc. I can launch a browser with the newly created ‘vpn-mullvad’, it connects perfectly, the network manager icon works etc. All perfect.

But if I try get any other app vm to connect via the newly created vpn-mullvad I can’t get this app vm, or any others to connect to the internet.

Does anybody have any idea what is happening to stop other vms from using this newly created app vm (mullvad) to access the internet?

As I said, I’ve gone over these instructions and I cannot for the life of me see what is going on to stop this connection. I’ll be very appreciative if anyone can throw some light on what might be preventing this. I posted some time back with this exact problem but unfortunately no solution was identified.

Same here - never got the micah solution working in the last couple of month. I thought it may have to do with the new QubesOS 4.1… And so I decited to create a new step by step file from my setup, I recently did from all the infos, I got from the last couple of weeks.

WireGuard on Qubes OS


Last updated: 27 May 2022

In this guide we will set up a ProxyVM called "MullvadVPN" which will provide network to other AppVMs, using WireGuard. If you want to use OpenVPN instead then see our guide Mullvad on Qubes OS 4.
	Note: We will use Sweden (se9-wireguard) as the server in this guide. If you want to use another server then replace the configuration with that.

Create a new qube

Click on the Qubes app menu and then Create Qubes VM.

    1. Name and label: MullvadVPN.
    2. Type: Qube based on a template (AppVM).
    3. Template: fedora-34 (or later).
    4. Networking: default (sys-firewall).
    5. Advanced: Check (enable) provides network.
    6. lick on OK.

Download a WireGuard configuration

In another AppVM (not MullvadVPN) that you use for web surfing:

    1. Open a web browser and log in to our WireGuard configuration file generator.
    2. Select Linux as the platform and then click on Generate key.
    3. Select a country, a city and a server.
    4. Click on Download file.
    5. Click on the Qubes app menu and go to your current AppVM and open Files.
    6. Open the Downloads folder and right click on the downloaded WireGuard file.
    7. Select Copy To Other AppVM... and then enter MullvadVPN as the Target and click on OK.

Install WireGuard

We will install WireGuard in the Fedora-34 template so your MullvadVPN ProxyVM can use that.

    1. Click on the Qubes app menu and go to Template: fedora-34 and open the Terminal.
    2. In the Terminal run the command sudo dnf install wireguard-tools -y
    3. Shut down the VM with the command sudo shutdown -h now

Set the Networking

    1. Click on the Qubes app menu and go to System Tools > Qube Manager.
    2. Select the AppVM that you want to use with the MullvadVPN ProxyVM and click on the Stop button in the toolbar to shut it down.
    3. Right click on the same AppVM and then select Qube settings.
    4. On the Basic tab, click on the Networking drop-down list and select MullvadVPN.
    5. Click on OK.
    6. Click on the Start button in the toolbar to start the AppVM again.

Configure WireGuard

In the MullvadVPN ProxyVM:

    1. Click on the Qubes app menu and go to MullvadVPN and open the Terminal.
    2. Now you will copy the WireGuard .conf file that was copied from the other AppVM to the /home/user/ folder so it persist after reboot. First run: cd /home/user/QubesIncoming/*
    	Then run: cp mlvd*.conf /home/user
    3. Now you will edit the /rw/config/rc.local file using a text editor. First install nano:
    	sudo dnf install nano -y
    4. Then run sudo nano /rw/config/rc.local
    5. Add wg-quick up /home/user/mlvd-se9.conf (or the config file you used) on a new line.
    6. Press Ctrl+O (Enter) and then Ctrl+X to save and exit.

Make sure that WireGuard connects:

    1. Run sudo wg-quick up /home/user/mlvd-se9.conf
    2. Run curl
    3. Run sudo wg and check for a handshake.

Add DNS hijacking rules

Now we will add firewall rules to redirect DNS requests to (the DNS on the VPN server) for all AppVMs that use the MullvadVPN ProxyVM.
Make sure that you have started an AppVM that has the Networking set to MullvadVPN, otherwise the "vif" IP address will not be visible.
Still in the MullvadVPN Terminal:

    1. To find out your vif* IP address, run ip a | grep -i vif
    2. Edit the firewall user file with nano:
    	sudo nano /rw/config/qubes-firewall-user-script
    3. Copy and paste the following in the bottom. Replace with your own vif* IP address:

	# replace with the IP address of your vif* interface
	iptables -F OUTPUT
	iptables -I FORWARD -o eth0 -j DROP
	iptables -I FORWARD -i eth0 -j DROP
	iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS  --clamp-mss-to-pmtu
	iptables -F PR-QBS -t nat
	iptables -A PR-QBS -t nat -d $virtualif -p udp --dport 53 -j DNAT --to $vpndns1
	iptables -A PR-QBS -t nat -d $virtualif -p tcp --dport 53 -j DNAT --to $vpndns1

    4. Press Ctrl+O (Enter) and then Ctrl+X to save and exit.

Add qube firewall rules

In Qube Manger, select MullvadVPN then right click and select Qube settings.

Make the following changes:

    1. Ensure it is still set to use sys-firewall as "Networking".
    2. Check "Start qube automatically on boot".
    3. Click on the "Firewall rules" tab.
    4. Click on "Limit outgoing internet connections to ...".
    5. Click on "+" and enter the IP addresses of the VPN servers that you want to be able to connect to. You can find it in the WireGuard configuration file (mlvd-se9.conf) on the Endpoint line, or in our Servers list.
    6. Click on OK.

Disable ping replies

    1. Click on the Qubes app menu and open Terminal Emulator.
    2. Run qvm-firewall MullvadVPN list. Find the rule in the bottom that says "accept icmp" and note the line number. If you have one line only - ignore next step and move on with step 4
    3. Run qvm-firewall MullvadVPN del --rule-no NUMBER. Replace NUMBER with the line number you found above.
    4. Run qvm-firewall MullvadVPN add --before NUMBER drop proto=icmp. Replace NUMBER with the line number you found above. This new rule will be added before the last "drop" line.
    5. Check it by running the list command again. The rules should be in this order: accept (the IP addresses of the VPN servers), accept dns, drop icmp, drop.

If you need to add (or remove) more firewall rules in Qube Manager for the MullvadVPN ProxyVM then you will need to edit the qvm-firewall with the steps above again.

This works for me. I also used the “placeholder” on the Mullvad VPN Configurator to grab/download all possible VPN exit nodes (must be around 100) configs in ‘one click’. So I have them available in my Mullvad-VPN template, where I created 5 or 6 VPNappVMs from - I need for daily driving.

Thanks for that. When I tried it before it was on the release of qubes before this one so I don’t know that is the issue. There is nothing worse than posting something and then having a bunch of people say that they had no problems doing it! I am so certain that Micah’s method does not work now, whereas it may have worked once.

Thank you for posting this solution. I will give it a go, probably not until next weekend now and see how it goes.

This is a great guide, thank you for creating it. It did work for me using the debian template as well. When installing wireguard-tools, I’d also mention installing resolvconf. It wasn’t a dependency for me and without it dns didn’t work.

When trying to disable ping replys, it shows now 0. Accept VPN IP, 1. Accept DNS 2. Drop icmp 3. Accept icmp 4. Drop. Not sure if removing 3 is necessary in this case.

Also noticed that I set “Limit outgoing connections to …” on the Firewall rules tab as mentioned to the VPN IP (without using a port number and without setting tcp or udp). After trying to disable ping replys, that tab is not usable anymore (it says Firewall has been modified manually. Please use the “qvm-firewall” command in dom0 for any further configuration).

1 Like

Did someone manage to have different VPN-qubes using the setup above?

The first qube I created works fine. The second qube trying to use the same VPN setup but a different server simply does not seem to have a network connection (although ip a output looks basically the same like in the first qube).

strange! Actually it (every VPN app cube) should be coming from the very same template (i.e. Fedora 36 here) and just the mlvd*.conf file under /home/user/ is different (…and the /rw/config/rc.local is edited)

@TheGardener Thanks, it looks I messed up something when trying to do this setup on a basic qube. Now I tried to simply clone the Mullvad qube and change the appropriate settings → success!

Here are the steps I had:

  • Clone the working Mullvad qube

  • Open terminal of the cloned qube and change the server of the wg-quick command in /rw/config/rc.local

  • Change the firewall rule for the new Mullvad qube in the dom0 terminal:
    qvm-firewall Mullvad-new list
    qvm-firewall Mullvad-new del --rule-no 0
    qvm-firewall Mullvad-new add --before 0 accept (<-here use the ip of the mullvad server given by the wg-quick command)

  • Add the new Mullvad qube as networking to an other qube and open the browser from this qube in order to check the vif ip in the Mullvad-new terminal:
    ip a | grep -i vif

  • Change the vif ip in: sudo vi /rw/config/qubes-firewall-user-script

  • Restart the Mullvad-new qube

After restart checking the connection should show the connected mullvad server: curl