Mullvad VPN App 4.2 setup guide

Original forum link
https://forum.qubes-os.org/t/25107
Original poster
Solène R
Editors
apparatus, DVM
Created at
2024-03-15 15:03:04
Last wiki edit
2024-09-15 12:49:01
Revisions
6 revisions
Posts count
146
Likes count
31

Intro

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/

Setup

Qube creation

Qube configuration

sudo dnf config-manager --add-repo https://repository.mullvad.net/rpm/stable/mullvad.repo
sudo dnf install mullvad-vpn
- Reboot the qube

Mullvad App

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.

Fix DNS

ℹ️ 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 the inotify-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 &

Avoid issues with WireGuard

ℹ️ 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©.

Killswitch configuration (easy method)

ℹ️ 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