From 93f0211f612776495d18ee8a06a6c698141e5483 Mon Sep 17 00:00:00 2001 From: ttasket Date: Thu, 15 Sep 2016 08:14:54 -0400 Subject: [PATCH] Update vpn.md * Scripts and text mention openvpn only in the context of examples. * Firewall commands slightly tweaked: Important blocking rules move to top. Removed superfluous check for qvpn OUTPUT rule. * Clarifications, especially mentioning that NM shouldn't be enabled for iptables/scripts option (this was causing DNS to fail for people who tried both NM and scripts). * Tells the user when and what they should test (iptables/scripts). * Change script order to enable testing flow. * Added Usage and Troubleshooting sections. https://github.com/QubesOS/qubes-issues/issues/2317 --- configuration/vpn.md | 168 ++++++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/configuration/vpn.md b/configuration/vpn.md index b718a9c8..117746df 100644 --- a/configuration/vpn.md +++ b/configuration/vpn.md @@ -12,9 +12,9 @@ redirect_from: How To make a VPN Gateway in Qubes ---------------------------------- -Setting up a VPN connection is really not Qubes specific and is documented in your operating system documentation. 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) +Although setting up a VPN connection is not by itself Qubes specific, there are a number of Qubes-related details that can make using the connection 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. -The Qubes specific part is to choose the right VM for the VPN client: +Please refer to 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) ### NetVM @@ -29,22 +29,18 @@ While the NetworkManager service is not started here (for a good reason), you ca ### ProxyVM - -**WARNING:** *You need to use Qubes 3.1-rc2 (or later)! In the previous releases the NetworkManager service was not working in ProxyVMs as expected.* ([#1052](https://github.com/QubesOS/qubes-issues/issues/1052)) - -One of the best thing in Qubes is that you can use a special type of VM called a ProxyVM (or FirewallVM). The special thing is that your AppVMs see this as a NetVM, and your NetVMs see it as an AppVM. Because of this, you can place a ProxyVM between your AppVMs and your NetVM. This is how the default FirewallVM functions. +One of the best things in Qubes is that you can use a 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. Using a ProxyVM to set up a VPN client gives you the ability to: -- Separate your VPN credentials from Your NetVM +- Separate your VPN credentials from Your NetVM. - Separate your VPN credentials from Your AppVM data. - Easily control which of your AppVMs are connected to your VPN by simply setting it as a NetVM of the desired AppVM. -#### Set up a ProxyVM as a VPN gateway +Set up a ProxyVM as a VPN gateway using NetworkManager +------------------------------------------------------ -#### Using NetworkManager - -1. Create a new VM and check the ProxyVM radio button. +1. Create a new VM: Name it, click the ProxyVM radio button then choose a color and template. ![Create\_New\_VM.png](/attachment/wiki/VPN/Create_New_VM.png) @@ -60,67 +56,40 @@ Using a ProxyVM to set up a VPN client gives you the ability to: 5. Optionally, you can install some [custom icons](https://github.com/Zrubi/qubes-artwork-proxy-vpn) for your VPN -#### Using iptables and openvpn -1. Create a new VM and check the ProxyVM radio button. +Set up a ProxyVM as a VPN gateway using iptables and CLI scripts +---------------------------------------------------------------- + +This method is more involved than the one above, but has anti-leak features that also make the connection _fail closed_ should it be interrupted. It has been tested with Fedora 23 and Debian 8 templates. + +1. Create a new VM: Name it, click the ProxyVM radio button then choose a color and template. ![Create\_New\_VM.png](/attachment/wiki/VPN/Create_New_VM.png) - If your choice of template VM doesn't already have the `openvpn` package, you'll need to install it in the template first. You may also need to `systemctl disable` any openvpn service that comes with the package if you follow the instructions for autostart below. - -2. Set up OpenVPN. - - Copy your openvpn config files to `/rw/config/openvpn/` folder. The example main config file is `openvpn-client.ovpn`. - - It should have one line that reads `dev tun`. - - If it does not contain a line `redirect-gateway def1` you may wish to add it. This will route all traffic through your vpn's network device after a connection is created. However, many VPN services will push this instruction to your client automatically -- having a line that says `client` or `pull` in your openvpn config instructs your client to use parameters specified by the VPN server. + Note: Do not enable NetworkManager, as it can interfere with the scripts' DNS features. If you used NetworkManager or other method in a previous attempt, do not re-use the old ProxyVM... Create a new one according to this step. - NOTE: If the connection breaks down all traffic will by default be routed through the upstream network device eth0 (we will stop this with iptables in step 3). + If your choice of template VM doesn't already have the VPN client software, you'll need to install the software in the template before proceeding. Disable any auto-starting service that comes with the software package: for example `sudo systemctl disable openvpn.service`. + + You may also wish to install `nano` or other simple text editor for entering the scripts below. - Also add the following to accomodate a DNS script: +2. Set up and initial test of the VPN client. - ~~~ - script-security 2 - up 'qubes-vpn-handler.sh up' - down 'qubes-vpn-handler.sh down' - ~~~ + Make sure the VPN VM and its template VM are not running. + + Run a terminal (CLI) in the VPN VM -- this will start the VM. Then make a new 'vpn' folder with `sudo mkdir /rw/config/vpn` and copy your VPN config files here (the example config filename used here is `openvpn-client.ovpn`). Files accompanying the main config such as *.crt and *.pem should also go here, and should not be referenced in the main config by absolute paths such as '/etc/...'. + + Notes about VPN config options: 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`. Lastly, the VPN client may not be able to prompt you for credentials when connecting to the server: Creating a file in the 'vpn' folder with your credentials and using a directive such as openvpn's `auth-user-pass ` is recommended. + + __Test your client configuration:__ Run the client from a CLI prompt in the 'vpn' folder, preferably as root. For example: + ``` + sudo openvpn --cd /rw/config/vpn --config openvpn-client.ovpn + ``` + + Watch for status messages that indicate whether the connection is successful and test from another VPN VM terminal window with `ping` and `traceroute`. 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. Set up iptables. - - Edit the firewall script with `sudo nano /rw/config/qubes-firewall-user-script` and add: - - ~~~ - #!/bin/bash - # First, block all outgoing traffic - iptables -P OUTPUT DROP - iptables -F OUTPUT - - # Add the `qvpn` group to system, if it doesn't already exist - if ! grep -q "^qvpn:" /etc/group ; then - groupadd -rf qvpn - sync - fi - sleep 2s - - # Allow traffic from the `qvpn` group to the uplink interface (eth0); - # Our openvpn will run as group `qvpn`. - iptables -A OUTPUT -p all -o eth0 -m owner --gid-owner qvpn \ - -m state --state NEW,ESTABLISHED -j ACCEPT - - # Allow internal system connections: - iptables -I OUTPUT -o lo -j ACCEPT - - # 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 - ~~~ - - Now save `/rw/config/qubes-firewall-user-script` and make it executable: - `sudo chmod +x /rw/config/qubes-firewall-user-script` - -4. Create the DNS-handling script. +3. Create the DNS-handling script. Use `sudo nano /rw/config/openvpn/qubes-vpn-handler.sh` to edit and add: ~~~ @@ -131,10 +100,10 @@ Using a ProxyVM to set up a VPN client gives you the ability to: case "$1" in up) - # To override DHCP DNS, assign static DNS addresses with 'setenv vpn_dns' in openvpn config; - # Format is 'X.X.X.X Y.Y.Y.Y [...]' with quotes. + # 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 options from openvpn to set DNS address translation: + # Parses DHCP foreign_option_* vars to automatically set DNS address translation: for optionname in ${!foreign_option_*} ; do option="${!optionname}" unset fops; fops=($option) @@ -164,25 +133,78 @@ Using a ProxyVM to set up a VPN client gives you the ability to: Now save the script and make it executable: `sudo chmod +x /rw/config/openvpn/qubes-vpn-handler.sh` +4. Configure client to use the DNS handling script. Using openvpn as an example, edit the config with `sudo nano /rw/config/vpn/openvpn-client.ovpn` and add these lines: + ~~~ + script-security 2 + up 'qubes-vpn-handler.sh up' + down 'qubes-vpn-handler.sh down' + ~~~ + + **Restart the client and test the connection again** ...this time from an AppVM! + +5. Set up iptables anti-leak rules. + + Edit the firewall script with `sudo nano /rw/config/qubes-firewall-user-script` then clear out the existing lines and add: + + ~~~ + #!/bin/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 + + # Block all outgoing traffic + iptables -P OUTPUT DROP + iptables -F OUTPUT + iptables -I OUTPUT -o lo -j ACCEPT + + # Add the `qvpn` group to system, if it doesn't already exist + if ! grep -q "^qvpn:" /etc/group ; then + groupadd -rf qvpn + sync + fi + sleep 2s + + # Allow traffic from the `qvpn` group to the uplink interface (eth0); + # Our VPN client will run with group `qvpn`. + iptables -I OUTPUT -p all -o eth0 -m owner --gid-owner qvpn -j ACCEPT + ~~~ + + Now save the script and make it executable: + `sudo chmod +x /rw/config/qubes-firewall-user-script` + 5. Set up the VPN's autostart. - Use `sudo nano /rw/config/rc.local` to edit and add: + Use `sudo nano /rw/config/rc.local` to clear out the existing lines and add: ~~~ #!/bin/bash + VPN_CLIENT='openvpn' + VPN_OPTIONS='--cd /rw/config/vpn/ --config openvpn-client.ovpn --daemon' + + su - -c 'notify-send "$(hostname): Starting $VPN_CLIENT..." --icon=network-idle' user groupadd -rf qvpn ; sleep 2s - sg qvpn -c 'openvpn --cd /rw/config/openvpn/ --config openvpn-client.ovpn \ - --daemon --writepid /var/run/openvpn/openvpn-client.pid' + sg qvpn -c "$VPN_CLIENT $VPN_OPTIONS" ~~~ + + Change the `VPN_CLIENT` and `VPN_OPTIONS` variables to match your VPN software. Now save the script and make it executable: `sudo chmod +x /rw/config/rc.local` -6. Restart the new VM! +6. Restart the new VM! The link should then be established automatically with a popup notification to that effect. -7. Configure your AppVMs to use the new VM as a NetVM. +Usage +----- + +Configure your AppVMs to use the VPN VM as a NetVM... ![Settings-NetVM.png](/attachment/wiki/VPN/Settings-NetVM.png) -8. Optionally, you can install some [custom icons](https://github.com/Zrubi/qubes-artwork-proxy-vpn) for your VPN +Troubleshooting +--------------- +* 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.