Although setting up a VPN connection is not by itself Qubes specific, Qubes includes a number of tools that can make the client-side setup of your VPN more versatile and secure. This document is a Qubes-specific outline for choosing the type of VM to use, and shows how to prepare a ProxyVM for either NetworkManager or a set of fail-safe VPN scripts.
Please refer to your guest OS and VPN service documentation when considering the specific steps and parameters for your connection(s); The relevant documentation for the Qubes default guest OS (Fedora) is [Establishing a VPN Connection.](https://docs.fedoraproject.org/en-US/Fedora/23/html/Networking_Guide/sec-Establishing_a_VPN_Connection.html)
The simplest case is to set up a VPN connection using the NetworkManager service inside your NetVM. Because the NetworkManager service is already started, you are ready to set up your VPN connection. However this has some disadvantages:
While the NetworkManager service is not started here (for a good reason), you can configure any kind of VPN client in your AppVM as well. However this is only suggested if your VPN client has special requirements.
One of the best unique features of Qubes OS is its special type of VM called a ProxyVM. The special thing is that your AppVMs see this as a NetVM (or uplink), and your NetVMs see it as a downstream AppVM. Because of this, you can place a ProxyVM between your AppVMs and your NetVM. This is how the default sys-firewall VM functions.
nmcli connection up file-vpn-conn passwd-file /rw/config/NM-system-connections/secrets/passwd-file.txt
```
You can find the actual "file-vpn-conn" in `/rw/config/NM-system-connections/`.
Create directory `/rw/config/NM-system-connections/secrets/` (You can put your `*.crt` and `*.pem` files here too).
Create a new file `/rw/config/NM-system-connections/secrets/passwd-file.txt`:
```
vpn.secrets.password:XXXXXXXXXXXXXX
```
And substitute "XXXXXXXXXXXXXX" for the actual password.
The contents of `passwd-file.txt` may differ depending on your VPN settings. See the [documentation for `nmcli up`](https://www.mankier.com/1/nmcli#up).
5. Make the network fail-close for the AppVMs if the connection to the VPN breaks.
Edit `/rw/config/qubes-firewall-user-script` and add these lines:
```bash
# Block forwarding of connections through upstream network device
# (in case the vpn tunnel breaks):
iptables -I FORWARD -o eth0 -j DROP
iptables -I FORWARD -i eth0 -j DROP
```
6. Configure your AppVMs to use the new VM as a NetVM.
The VPN scripts here are intended to work with commonly used `tun` interfaces, whereas `tap` mode is untested.
Also, the config should route all traffic through your VPN's interface after a connection is created; For OpenVPN the directive for this is `redirect-gateway def1`.
`ping` can be aborted by pressing the two keys `ctrl` + `c` at the same time.
DNS may be tested at this point by replacing addresses in `/etc/resolv.conf` with ones appropriate for your VPN (although this file will not be used when setup is complete).
Diagnose any connection problems using resources such as client documentation and help from your VPN service provider.
Proceed to the next step when you're sure the basic VPN connection is working.
3. Create the DNS-handling script.
sudo nano /rw/config/vpn/qubes-vpn-handler.sh
Edit and add:
~~~
#!/bin/bash
set -e
export PATH="$PATH:/usr/sbin:/sbin"
case "$1" in
up)
# To override DHCP DNS, assign DNS addresses to 'vpn_dns' env variable before calling this script;
# Format is 'X.X.X.X Y.Y.Y.Y [...]'
if [[ -z "$vpn_dns" ]] ; then
# Parses DHCP foreign_option_* vars to automatically set DNS address translation:
for optionname in ${!foreign_option_*} ; do
option="${!optionname}"
unset fops; fops=($option)
if [ ${fops[1]} == "DNS" ] ; then vpn_dns="$vpn_dns ${fops[2]}" ; fi
* Always test your basic VPN connection before adding scripts.
* Test DNS: Ping a familiar domain name from an appVM. It should print the IP address for the domain.
* For scripting: Ping external IP addresses from inside the VPN VM using `sudo sg qvpn -c 'ping ...'`, then from an appVM using just `ping ...`. Once the firewall rules are in place, you will have to use `sudo sg` to run any IP network commands in the VPN VM.
* Use `iptables -L -v` and `iptables -L -v -t nat` to check firewall rules. The latter shows the critical PR-QBS chain that enables DNS forwarding.