Qubes OS: Setting Up VPN5 April 2022 2023-07-15 15:28
Qubes OS: Setting Up VPN
Qubes OS: Setting Up VPN
We’ll be setting up the VPN by giving it its own Qube (VM, virtual machine). This way we can swap it in between other Qubes according to whatever configuration we want or leave it out altogether. We’ll be using Mullvad as an example but as long as you exchange the Mullvad configuration items with your VPN providers information it should work as well. If you rather use Mullvad’s way of setting up a VPN in Qubes, their tutorial can be found here: https://mullvad.net/en/help/qubes-os-4-and-mullvad-vpn/ We’ll be using the NetworkManager system tray applets so we can always see if the VPN is connected or not. On top of that we’ll set up a simple script to automatically connect to the VPN every time the VPN Qube starts, and it will reconnect it in case it disconnects. Additionally we’ll set up the Qubes firewall rules to prevent any non-VPN traffic from leaking and sneaking past the VPN.
The VPN Qube
Start by creating a new VM called “vpn-mullvad”. (You can name it whatever you want, just make sure to use that name in the next steps instead.)
Make sure the type is set to “Qube based on a template (AppVM). Use the latest Fedora template that you have. Set it to network to “sys-firewall” and not “default (sys-firewall)”. Check both the “provides network” and “launch settings after creation” boxes. “Provides network” means this new VM will be able to provide internet access to other VMs.
When the vpn-mullvad settings open, go to the “Services” tab. Add a service called “network-manager”. Then click ok. This will make it so that a NetworkManager system tray applet in the top-right corner of your screen shows every time this VM starts.
Get The VPN Configuration
Open a web browser in a disposable VM: Click the Qubes menu, go to one of the “Disposable” items (there could be more than one if you have multiple templates set as disposable.) and then start Firefox or any other browser of your choice. Login to your Mullvad account at https://mullvad.net/en/account/login/. Go to Mullvad’s OpenVPN configuration file generator. (https://mullvad.net/en/download/config/). Set your platform to “Linux”. Choose a location. Make sure to check Use IP addresses. Then click download. We’ll use Canada in this setup so we’re getting a file called “mullvad_config_linux_ca.zip”.
Open a file manager in your disposable VM that contains the file you just downloaded. You can do this from the download list in your browser or start a file manager from the Qubes menu.
Copy the file to your “vpn-mullvad” VM. Click right on the file and the context menu shows an option to copy to another AppVM.
Select the “vpn-mullvad” VM as your target in the popup and click ok. This will probably boot that VM for the first time.
Open a file manager in your “vpn-mullvad”VM: Click the Qubes menu, then Service: vpn-mullvad, then vpn-mullvad: Files). Navigate to the “QubesIncoming” folder. Inside here will be a folder with the name of your disposable VM. Open this folder. You should see the zip file that was dowloaded earlier from Mullvad. Right-click on it and choose “Extract Here”. Drag the extracted folder (“mullvad_config_linux_ca”, in this example) to the “Documents” folder. Navigate to the “Documents” folder and open the “mullvad_config_linux_ca” folder. You should see your VPN configuration files.
You may have noticed that a new NetworkManager icon appeared in you system tray when the “vpn-mullvad” VM started.
Click on the new NetworkManager icon. Go to “VPN Connections” and then click on “Add a VPN connection…”.
A popup appears. Select “Import a saved VPN configuration…” from the dropdown list. Click on Create.
Then browse for the Mullvad .conf file in your Documents folder.
A configuration window will appear. To fill this in, we’ll need the username and password we got from Mullvad. In your file manager, go to the Mullvad configuration files in the “Documents” folder. Open the file “mullvad_userpass.txt”. There you will find the username and password. Copy them to their respective fields in the configuration window. Click Save.
A window will open, asking you to set a password for the default keyring. Leave it blank and click Continue. Confirm you want to store passwords unencrypted by clicking Continue again. Everything on the system is already encrypted with full disk encryption and we won’t be running any other software in this Qube/VM that could access these files.
Click the vpn-mullvad NetworkManager system tray icon. Click “VPN Connections” and then connect to the new VPN just added. It should attempt to connect. If successful, a notification will appear that reads: “VPN connection has been successfully established”. The NetworkManager icon will have a small lock next to it.
Connect At Startup
Let’s get the VPN to connect automatically at startup so you don’t have to do that manually every time. Open a terminal in the vpn-mullvad VM: click Qubes > Service: vpn-mullvad > vpn-mullvad: Terminal. Run this in the terminal:
sudo gedit /rw/config/autovpn.sh
This will open a blank file in gedit, named autovpn.sh. You can use whatever editor you want though. Copy and paste this script into it:
while [ "true" ]
if nmcli con |grep -Fq tun0
echo "Already connected, sleeping 5"
nmcli con up mullvad_ca
Change the line that says “nmcli con up mullvad_ca” to use the name of the VPN config that you added, assuming you chose a location other than Canada. Save the file and quit the editor.
This script checks if you are connected to the VPN. If you are, it waits 5 seconds and checks again. If you’re not, it connects you to the VPN. It keeps doing this so if you ever get disconnected, it will detect this and reconnect.
Go back to the Terminal and make the “autovpn.sh” file executable. Run this command:
sudo chmod +x /rw/config/autovpn.sh
Now edit the rc.local file. Run this command:
sudo gedit /rw/config/rc.local
Put this line at the end of this “rc.local” file:
sudo -u user /rw/config/autovpn.sh &
Save the file and exit.
The rc.local script runs every time the VM boots. This will then run the autovpn.sh script in the background.
You can test this right away by turning off the vpn-mullvad VM. To do this: Click the Qubes icon in the system tray > vpn-mullvad > Shutdown. Then turn the VM on again (Opening file manager in the VM will do the trick.) The VPN should connect automatically.
Programs will try to access the internet regardless of whether the VPN is connected or not. Maybe it didn’t connect yet or it got disconnected somehow. So let’s prevent these leaks from getting out. The Qubes firewall can prevent the vpn-mullvad VM from communicating with anything but the VPN servers that it is set to connect with. For example, the VPN gets disconnected while you have a web browser open. The browser won’t load anything from your real IP address. This traffic will get dropped by the firewall.
Open the file manager in vpn-mullvad. Go to the folder with the Mullvad config files. Open the “.config” file. There is a list of lines that start with “remote”. These are the various servers that Mullvad uses to connect to.
Open the settings for vpn-mullvad: Click the Qubes menu > go to Service: vpn-mullvad > vpn-mullvad: Qubes Settings. Go to the “Firewall rules” tab. Here you can add rules to allow IP addresses through while blocking all others (ie. whitelisting).
Qubes has difficulty with managing many rules (20+ something rules). For example, if you pick the US then there will be too many servers in the list. Simple add less addresses. If you do this, make sure to delete the VPN in NetworkManager and then add it again.
There is no simple way to copy from a VM to dom0. This is for security reasons. Copying will be a bit more tedius though. To get it as simply as possible, just view the file in dom0. Open a Terminal in dom0: Click the Qubes menu > open Terminal Emulator.
Run this command:
qvm-run --pass-io vpn-mullvad 'cat ~/Documents/mullvad_*/*.conf' | grep "remote "
This will show all the “remote” lines from the Mullvad config file. From inside the dom0 Terminal window you can copy to the Qubes firewall rules.
Go back to the vpn-mullvad settings window. In the “Firewall rules” tab, select “Limit outgoing Internet connections to …”. Then click the plus button and add a rule for each IP address. Copy and paste from the dom0 Terminal if you prefer. It is fine to set the protocol to “Any” for each rule.
Then click OK.
You’re done setting up vpn-mullvad. It uses the NetworkManager. It automatically connects, also when disconnected. With the vpn-mullvad VM as your networking VM, thanks to the firewall rules, all the downstream VMs won’t connect outside the VPN.
VPN By Default
You can have all your VMs use Mullvad by default or just change it for the one’s you want.
Open the Qubes Global Settings: Qubes menu > System Tools > Qubes Global Settings
Change the “Default netVM” from “sys-firewall” to “vpn-mullvad”.
You still can open a browser while not using the VPN. This might happen when using public wifi and there is a captive portal. You can make a disposable VM template just for this purpose.
Open the settings for “fedora-30-dvm” (Qubes menu, Disposable: fedora-30-dvm, fedora-30-dvm: Qube Settings). Click “Clone qube”. Rename the clone to “fedora-30-clearnet-dvm”.
Open the settings for “fedora-30-clearnet-dvm”. Change “Networking” from “default (vpn-mullvad)” to “sys-firewall”. Click ok.
If you need to click through a captive portal, you can just open a browser in a “fedora-30-clearnet-dvm” disposable VM and click through the portal. As soon as you have internet, the vpn will automatically connect, and internet will work on the other VMs.