Back to Guides

Mullvad on Qubes OS 4

In this guide we will setup a ProxyVM called MullvadVPN, which will then proxy other APPVMs traffic. We will use Sweden as a region in this guide, if you prefer another region then replace se with that one.


    Click Create Qubes VM in Applications
    Name and label: MullvadVPN
    Type: Standalone qube based on a template
    Template: debian-9
    Networking: default (sys-firewall)
    Advanced: Check provides network


  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 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 VM to exit via the MullvadVPN proxy (the VM 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 VM 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 (2.4.0 in Debian9, you can of course install a newer one if you wish as well)

  • In a terminal issue: sudo apt-get update && apt-get install openvpn

Extract and copy the configuration files to /etc/openvpn

  • In a terminal change directory to where the configuration file is located
  • unzip the file (unzip
  • copy the files to /etc/openvpn/  ("sudo cp mullvad_config_linux_se/* /etc/openvpn/")

Enable autostart of OpenVPN

  • as root or with sudo edit /etc/default/openvpn and change #AUTOSTART="all" to AUTOSTART="all" (in other words, remove the "#")

Add DNS hijacking script

  • Add the follwing 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 issue:  ip a | grep -i vif in a terminal (make sure you have the APP VM 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. Set it 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).

You can also enter IP ranges for Sweden and the Netherlands:

  •  Sweden (Malmö)
  •  Sweden (Malmö)
  •  Sweden (Helsingborg)
  •  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


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 visit:

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. Replace the "remote" with "remote" (as a test, and if that works you can add more entries)

I followed the guide but I can not connect to anything from the APPVM. However, the PROXYVM connects properly and eveything 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.