This guide explains how to setup a a VPN with Mullvad app on Qubes OS 4.2 using a Fedora template.
Mullvad app is open source and they provide repositories for fedora / debian, there are no documentation to deploy the App, only an official page explaining how to setup WireGuard, or a community guide for Mullvad WireGuard without the App
The App supports OpenVPN and WireGuard tunnels. Bridge support is available for OpenVPN and WireGuard has obfuscation available, these features are useful if you are unable to connect due to censorship.
They seem also a legit service to use as per the trustable source https://www.privacyguides.org/en/vpn/
sys-vpn-mullvad-app
)qubes-firewall
sudo dnf config-manager --add-repo https://repository.mullvad.net/rpm/stable/mullvad.repo
sudo dnf install mullvad-vpn
Start the App with /opt/Mullvad\ VPN/mullvad-gui
or add "Mullvad VPN" application in the qube menu entry that should be available after the installation process.
The Mullvad VPN app should start without issue:
Auto start at boot can be enabled in the settings.
ℹ️ The App uses several custom DNS that change based on the options selected by the user, but this doesn't propagate to the qubes behind it, resulting in long latency times for resolving hostnames. The following script forces all DNS requests to automatically go through the selected custom DNS server.
⚠️ The script depends on
inotify
, which can be installed with theinotify-tools
package.
Edit the file /usr/local/bin/mullvad-dns.sh
to put the following content:
#! /usr/bin/env bash
update_dns() {
# mullvad_on: 0 -> off, 1 -> on
mullvad_on=$([[ $(grep -v -c "nameserver \+10.139" /etc/resolv.conf) -gt 0 ]] && echo 1 || echo 0)
if [[ $mullvad_on -eq 1 ]]; then
echo "Mullvad is on"
# get the mullvad dns ip address. First one is used if there is more than one.
mullvad_dns_ip=$(grep "nameserver" < /etc/resolv.conf| awk '{print $2}' | head -n 1)
# delete all the lines defined in dnat-dns
sudo nft flush chain ip qubes dnat-dns
# forward all dns requests to mullvad dns servers
sudo nft add rule ip qubes dnat-dns meta l4proto { tcp, udp } ip daddr { 10.139.1.1, 10.139.1.2 } th dport 53 dnat to "$mullvad_dns_ip"
else
echo "Mullvad is off"
# get qubes nameserver ip addresses
nameserver_ips=$(grep "nameserver" < /etc/resolv.conf| awk '{print $2}')
# delete all the lines defined in dnat-dns
sudo nft flush chain ip qubes dnat-dns
# add rule to forward dns requests to qubes nameservers
for ip in $nameserver_ips; do
sudo nft add rule ip qubes dnat-dns ip daddr "$ip" udp dport 53 dnat to "$ip"
sudo nft add rule ip qubes dnat-dns ip daddr "$ip" tcp dport 53 dnat to "$ip"
done
fi
}
update_dns
# check for /etc/resolv.conf content change
inotifywait -m -q -e close_write /etc/resolv.conf | while read -r;
do
update_dns
done
Make the script executable
sudo chmod +x /usr/local/bin/mullvad-dns.sh
And add this to run the script at boot time to /rw/config/rc.local
/usr/local/bin/mullvad-dns.sh &
ℹ️ WireGuard tunnels can trigger a MTU issue in the network, in short it could make some websites not working (like duckduckgo) because of too big packet sizes. This is a common issue with WireGuard VPNs.
Add this to /rw/config/qubes-firewall-user-script
nft add rule ip qubes custom-forward tcp flags syn / syn,rst tcp option maxseg size set rt mtu
This will automatically ensure that the qubes network packets will fit in a WireGuard network packet and will make things works©.
ℹ️ You may want to force all qubes traffic to go through the VPN and block non-VPN traffic. Mullvad app offers a killswitch but the app could still crash and the killswitch wouldn't be guaranteed to work.
ℹ️ This easy method plays well with the App as you don't need to configure a firewall rule for each server/port. However, if the qube gets compromised it's possible to disable the rule, if you want more security against this threat you should use
qvm-firewall
.
Add the rules below in /rw/config/qubes-firewall-user-script
in the qube:
# Prevent the qube to forward traffic outside of the VPN
nft add rule qubes custom-forward oifname eth0 counter drop
nft add rule ip6 qubes custom-forward oifname eth0 counter drop