This method offers a more secure way to utilize VPNs when you seek similar security and (pseudo)anonymity advantages of the Whonix Workstation, but prefer not to use Tor as your exit node.
Clone your whonix-workstation-17
and name it whonix-workstation-17-vpn
Open a terminal in whonix-workstation-17-vpn template
Run
sudoedit /etc/uwt.d/50_user.conf
Add.
uwtwrapper_global="0"
Save and exit (Ctrl+S).
Verify that Stream Isolation is disabled by running:
uwt_settings_show
(Optional but highly recommended) Here’s a simple script to install the Mullvad Browser in the template:
# Configures tinyproxy
export https_proxy=http://127.0.0.1:8082
# Downloads the signing key
curl -fsSLo /usr/share/keyrings/mullvad-keyring.asc https://repository.mullvad.net/deb/mullvad-keyring.asc
# Add the Mullvad repository server to apt
echo "deb [signed-by=/usr/share/keyrings/mullvad-keyring.asc arch=$( dpkg --print-architecture )] https://repository.mullvad.net/deb/stable stable main" | sudo tee /etc/apt/sources.list.d/mullvad.list
# Install the package
apt update
apt install mullvad-browser
Template setup is complete! Now, let’s configure Mullvad for networking.
Clone a fedora-41 template and name it MullvadApp-TVM
Open a terminal in MullvadApp-TVM
Run this script by Tommy from PrivSec to minimize the template and reduce the attack surface: https://github.com/TommyTran732/QubesOS-Scripts/blob/main/fedora-gnome/fedora-gnome.sh
Create bind directories for Mullvad (So your Mullvad configuration stays after restart)
sudo mkdir -p /etc/qubes-bind-dirs.d
echo `binds+=( `\```/etc/mullvad-vpn``\`` )` | sudo tee /etc/qubes-bind-dirs.d/50_user.conf
Install Mullvad
sudo dnf config-manager addrepo --from-repofile=https://repository.mullvad.net/rpm/stable/mullvad.repo
sudo dnf install -y mullvad-vpn
Install inotify
sudo dnf install -y inotify-tools
Restart/Shutdown your template for the changes to take effect
Done with the MullvadApp-TVM template! Onto the AppVM
Create an AppVM based on your MullvadApp-TVM template, name it sys-mullvad and set your network qube to sys-firewall or sys-whonix if you want a VPN over Tor solution.
Checkmark "Launch settings after creation" and go to the Advanced tab and checkmark "Provide network access to other qubes". Click Ok.
In your settings window go to the Advanced tab and set both Initial memory and Max memory to 512. Click Ok.
Start your new sys-mullvad Qube and open a terminal. Run the command sudoedit /usr/local/bin/mullvad-dns.sh
and paste in the following contents:
#! /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)
# get the local ip address of qube vm.
qube_vm_ip=$(hostname -I | awk `{print $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 { "$qube_vm_ip" } 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 with
sudo chmod +x /usr/local/bin/mullvad-dns.sh
Configure rc.local to boot mullvad-dns.sh at Qube boot with this command
echo "/usr/local/bin/mullvad-dns.sh &" | sudo tee -a /rw/config/rc.local
Add this firewall rule to /rw/config/qubes-firewall-user-script
prevent a common MTU issue with Wireguard
nft add rule ip qubes custom-forward tcp flags syn / syn,rst tcp option maxseg size set rt mtu
(Optional) Add these firewall rules to /rw/config/qubes-firewall-user-script
to add another killswitch in case Mullvad`s fails for whatever reason
nft add rule qubes custom-forward oifname eth0 counter drop
nft add rule ip6 qubes custom-forward oifname eth0 counter drop
Keep in mind that when you create an AppVM with your sys-mullvad qube, it must be based on the whonix-workstation-17-vpn template.
Big thanks to Solene and Tommy from PrivSec as this guide is a mash of both their guides plus a bit of my own.