Mullvad on Qubes OS 4


Last updated: 6 March 2023

In this guide we will setup a ProxyVM called MullvadVPN, which will then proxy other APPVMs traffic.

Note: We will use Sweden as a region in this guide, if you prefer another region then replace se with that one.

This guide is using OpenVPN. For using WireGuard see the guide WireGuard on Qubes OS.


First install a Debian 11 template (if you do not already have it) by issuing the following in dom0: sudo qubes-dom0-update --enablerepo=qubes-templates-itl-testing qubes-template-debian-11

  1. Click Create Qubes VM in Applications
    1. Name and label: MullvadVPN
    2. Type: Standalone qube copied from a template
    3. Template: debian-11
    4. Networking: default (sys-firewall)
    5. Advanced: Check provides network access to other qubes
    6. Click OK

In an AppVM

  1. Open a browser and go to our Configuration files page.
  2. Enter your account number, select Linux as platform and then the region you wish to use, then enable Use IP addresses click on the Download button.
  3. Open a terminal and qvm-copy the downloaded .zip file(for instance  to the ProxyVM you created (MullvadVPN).

In the Qubes Manager

Assign a AppVM to exit via the MullvadVPN proxy (the AppVM must be started and assigned to the ProxyVM otherwise the vif on the ProxyVM will not be visible).

  1. Shut down that AppVM you wish to assign
  2. Select a AppVM right-click it and then select Qube settings  (or preferences if using the applet)
  3. In the Basic tab, change Networking: to  MullvadVPN
  4. Click on Apply and then OK
  5. Start the AppVM again.

In the MullvadVPN ProxyVM

Install OpenVPN

In Debian10, you can of course install a newer one if you wish as well.

In a terminal run sudo apt-get update && sudo apt-get install openvpn

Extract and copy the configuration files to /etc/openvpn

  1. In a terminal change directory to where the configuration file is located
  2. unzip the file (unzip
  3. To copy the files to /etc/openvpn/, run  sudo cp mullvad_config_linux_se/* /etc/openvpn/
  4. To set the execute permissions on it, run sudo chmod 755 /etc/openvpn/update-resolv-conf

Enable autostart of OpenVPN

Issue  sudo vi /etc/default/openvpn and change #AUTOSTART="all" to AUTOSTART="all" (in other words, remove the "#")
After that save and exit.

Add DNS hijacking script

Add the following to the file /rw/config/qubes-firewall-user-script be sure to change to the IP that matches your vif*

To find out your vif* ip address, run ip a | grep -i vif in a terminal (make sure you have the AppVM assigned before you do this, otherwise it will not show up).

# 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 -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
iptables -A PR-QBS -t nat -d $virtualif -p udp --dport 53 -j DNAT --to $vpndns2
iptables -A PR-QBS -t nat -d $virtualif -p tcp --dport 53 -j DNAT --to $vpndns2

This is to redirect DNS requests to and for all AppVMs that use the ProxyVM.

In Qubes Manager (again)

Select MullvadVPN then right-click and select Qube settings

Make the following changes:

  1. Ensure it is set to use sys-firewall as "Networking"
  2. Check "Start qube automatically on boot"
  3. Click on "Firewall rules"
  4. Click on "Limit outgoing internet connections to ..."
  5. Click on "+" and then enter the IP addresses of the VPN servers you wish to connect to.
  6. Click on Apply and then OK

For instance if you wish to connect to, then issue "nslookup" in a terminal and then enter that IP address (see our list of VPN servers), or you can download an OpenVPN configuration file with Use IP Addresses enabled in the Advanced settings and then look at the OpenVPN configuration for which IP-addresses it contains and then add them.

You can also enter IP ranges for Sweden and the Netherlands (ensure you add all IP ranges for a given location):

  •  Sweden (Malmö)
  •  Sweden (Malmö)
  •  Sweden (Malmö)
  •  Sweden (Helsingborg)
  •  Sweden (Gothenburg)
  •  Sweden (Stockholm)
  •  Netherlands (Amsterdam)

In Dom0

In Qubes R4 "ICMP and DNS are no longer accessible in the GUI, but can be changed via qvm-firewall".

  1. Open Terminal Emulator
  2. Run qvm-firewall MullvadVPN list. Based on that list we need to delete the rule that accepts icmp, and add a new rule that drops it.
  3. Run qvm-firewall MullvadVPN del --rule-no [icmp_rule_#]. Now to add the new icmp rule run the list command again, and add the icmp rule before the final "drop" line
  4. Run qvm-firewall MullvadVPN add --before [last_drop_rule_#] drop proto=icmp. Now you can verify 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

Keep in mind that you will need to edit the firewall rules in dom0 if you wish to add more ip-ranges.


How do I verify that traffic is going out via the MullvadVPN proxy?

Open a browser in your APPVM that is connected to the MullvadVPN proxy VM and go to our Connection check.

Why do you use a standalone VM?

You can of course do this in a regular AppVM as long as you have OpenVPN installed in it, having it standalone means you do not need to restart VM's as much if you want to update things, though it does take more diskspace.

I sometimes can't connect. Why?

Since OpenVPN will depend on DNS working unless you use IP addresses, it could be because your DNS replies are poisoned, or your DNS queries are blocked, the solution would then be to use IP addresses instead of host+domainnames for connecting. Open the OpenVPN configuration file located in /etc/openvpn/ and replace "remote" with "remote" (as a test, and if that works you can add more entries)

I followed the guide but can't connect to anything from the APPVM. However, the PROXYVM connects properly and everything works there.

Make sure you shut down your APPVM before setting the PROXYVM, it seems it does not work as well by changing it on the fly as it did in Qubes 3.2.