Split tunneling: Difference between revisions

From James's Wiki
No edit summary
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
<syntaxhighlight lang="bash">
=Force Torrent Traffic through VPN Split Tunnel Debian 8 + Ubuntu 16.04=
</syntaxhighlight>
It is very important to protect your online privacy. We would certainly recommend using a VPN (Virtual Private Network) with OpenVPN. Luckily, there are many paid VPN servers available with excellent performance at great price. Always read their Privacy Policy, consider the quality of the service for the price and choose one you trust. In this guide we will use Private Internet Access (PIA) as the VPN provider, in my experience configuring others will not differ too much.
 
Important: This guide is written for Ubuntu Server 16.04 LTS and Debian 8 systems (like Minibian, Raspbian, Bananian) that uses systemd services. It might work on other Linux distributions, but it is guaranteed to work on Ubuntu Server 16.04 LTS and Debian 8. For systems that use upstart script (like Ubuntu Server 14.04 LTS), upstart scripts are required instead of systemd service. If you are using Ubuntu Server 14.04 LTS, jump to the Force Torrent Traffic VPN Split Tunnel Ubuntu 14.04 guide.
 
The sections which are marked Minibian are needed only if you are, well, running Minibian. Ubuntu Server 16.04 LTS users should skip those parts (it will be always indicated in the relevant section).
 
==Why Split VPN Tunnel?==
If you are running a home server based on Ubuntu Server and you configure your OpenVPN client, you will be completely tunneled over the active VPN connection. But what if we would like to tunnel only few applications' traffic over VPN (for example Transmission or Deluge) and allow everything else direct connection? This is called split tunneling the VPN connection. What if your VPN connection breaks because the VPN server is offline? Without proper firewall rules you will automatically fall back to your direct Internet connection and immediately expose your real IP address. This poses privacy and anonymity risks!
 
==The Benefits of VPN Split Tunneling==
====Control====
You can select which services/applications should be tunneled over the VPN connection by running the selected services/application as vpn user, therefore you can protect your identity.
 
====Automation====
The VPN connection with Split Tunneling is started automatically on each system start, restarted automatically once the VPN provider is online again.
 
====Increased Safety====
If the VPN connection breaks, the vpn user is “disconnected” from the Internet (Automatic Kill Switch), if VPN connection is established again, vpn user will have access to Internet again over VPN. This ensures that your real IP address is never exposed publicly, only the IP address assigned by VPN provider is visible.
 
====Increased Convenience====
You retain you direct internet connection for all the other users, bypassing the VPN for services/applications that don't require you to hide your real IP address
 
====Keep Remote Access====
You will still be able to remotely manage your services by reverse proxy!
 
=Installation Overview=
This is an advanced guide but every effort has been made to make it friendly for new users with basic Linux knowledge. Should anything go wrong, feel free to comment or post on the Forum, we will do our best to help you. Since the publication of the VPN Split Tunnel guide for Ubuntu Server 14.04 LTS there are many interesting posts in the forum section.
 
This is Part 1 of the split tunnel guide. In this guide you will create and configure the vpn user.
 
In Part 2 of upcoming guides you will configure your torrent client (Transmission or Deluge) to run as the VPN user.
 
Here is an overview of all the steps in Part 1:
 
Install and configure OpenVPN (including auto connecting to VPN server on system start)
Modify PIA configuration file to adjust for Split Tunneling
Configure DNS Server for VPN connection to prevent DNS leak
Create the vpn user that will be tunneled over VPN
Use iptables to mark vpn user's traffic and routing rules to route marked packets over VPN connection
Check everything is configured and working correctly
==Install openvpn==
fortunately, the Ubuntu and Debian repositories are not always up to date. It is recommended to use the latest OpenVPN release to make sure you have the latest security fixes (and possible updates). In case of Ubuntu Server 16.04 the official OpenVPN repository always provides the latest version. In case of ARM CPUs like the Rasperry Pi running Raspbian or Minibian, we need to build the latest version since the OpenVPN repository doesn't provide builds for ARM based devices. It is quite easy to build OpenVPN from source (stay tuned for the guide), until then, on Debian, Minibian and Raspbian you can use the version available in the Debian repository.
 
Install OpenVPN on Ubuntu Server 16.04 LTS
If you are using Ubuntu Server 16.04 LTS we will install OpenVPN from the official OpenVPN repository. First import the public GPG key that is used to sign the packages.
 
wget https://swupdate.openvpn.net/repos/repo-public.gpg -O - | sudo apt-key add -
Add the OpenVPN repository
 
echo "deb http://build.openvpn.net/debian/openvpn/stable xenial main" | sudo tee -a /etc/apt/sources.list.d/openvpn.list
Install OpenVPN
 
sudo apt-get update
sudo apt-get install openvpn -y
Update: OpenVPN apt repository has changed, the guide has been updated with the new address.
 
Install OpenVPN on Debian 8 (Minibian, Raspbian)
Since OpenVPN repository doesn't support ARM based devices, we have two options. Use the OpenVPN version available in the Debian repository (probably quite outdated version), or build the latest OpenVPN version from source following our guide. I strongly recommend to build OpenVPN to get the latest version. If you decide to build OpenVPN from source, then skip the below two lines.


setup openvpn
This will install OpenVPN from the Debian repository (required only if you didn't build OpenVPN from source)


apt-get update
apt-get install openvpn -y
create systemd service file for openvpn
create systemd service file for openvpn


Line 112: Line 171:
Thanks to a feedback by our member Jesus, we are now addressing a vulnerability related to the VPN Split Tunnel implementation. If the PIA login credentials are not correct, then OpenVPN will not establish the VPN connection, therefore the firewall rules are not applied (since OpenVPN will execute up scripts only on successful connection). The result is not having the kill switch enabled (iptables rules loaded) and vpn user has direct access to Internet. To prevent this scenario, we will implement a permanent firewall rule to block vpn user’s access to Internet until the OpenVPN tunnel is up and functional, and the required scripts are started. This will prevent any IP leaks even if no connection to PIA is possible for any reason.
Thanks to a feedback by our member Jesus, we are now addressing a vulnerability related to the VPN Split Tunnel implementation. If the PIA login credentials are not correct, then OpenVPN will not establish the VPN connection, therefore the firewall rules are not applied (since OpenVPN will execute up scripts only on successful connection). The result is not having the kill switch enabled (iptables rules loaded) and vpn user has direct access to Internet. To prevent this scenario, we will implement a permanent firewall rule to block vpn user’s access to Internet until the OpenVPN tunnel is up and functional, and the required scripts are started. This will prevent any IP leaks even if no connection to PIA is possible for any reason.


Flush current iptables rules
===Flush current iptables rules===
 
<syntaxhighlight lang="bash">
sudo iptables -F
sudo iptables -F
</syntaxhighlight>
Add the following rule, which will block vpn user's access to Internet (except the loopback device). Note, if you configured Split Tunnel with different user then vpn, then change vpn marked in red to the user you used.
Add the following rule, which will block vpn user's access to Internet (except the loopback device). Note, if you configured Split Tunnel with different user then vpn, then change vpn marked in red to the user you used.
 
<syntaxhighlight lang="bash">
sudo iptables -A OUTPUT ! -o lo -m owner --uid-owner vpn -j DROP
sudo iptables -A OUTPUT ! -o lo -m owner --uid-owner vpn -j DROP
</syntaxhighlight>
Now install iptables-persistent to save this single rule that will be always applied on each system start.
Now install iptables-persistent to save this single rule that will be always applied on each system start.
 
<syntaxhighlight lang="bash">
sudo apt-get install iptables-persistent -y
sudo apt-get install iptables-persistent -y
</syntaxhighlight>
During the install, iptables-persistent will ask you to save current iptables rules to /etc/iptables/rules.v4 as seen on the screenshot, accept this with YES
During the install, iptables-persistent will ask you to save current iptables rules to /etc/iptables/rules.v4 as seen on the screenshot, accept this with YES
iptables_persistent_split_tunnel-min


Now when system starts, vpn user is not able to access Internet. If the OpenVPN service is started successfully, then this rule is flushed (only until the next system restart), and the Split Tunnel rules are applied.
Now when system starts, vpn user is not able to access Internet. If the OpenVPN service is started successfully, then this rule is flushed (only until the next system restart), and the Split Tunnel rules are applied.


iptables Script for vpn User
===iptables Script for vpn User===
The first script will mark the packets for vpn user, the second script will take care of proper routing.
The first script will mark the packets for vpn user, the second script will take care of proper routing.


Create the iptables script
====Create the iptables script====
 
<syntaxhighlight lang="bash">
sudo nano /etc/openvpn/iptables.sh
sudo nano /etc/openvpn/iptables.sh
</syntaxhighlight>
Copy the following to the iptables.sh script, and make sure you enter the network interface and the local IP we identified and marked with red and blue respectively.
Copy the following to the iptables.sh script, and make sure you enter the network interface and the local IP we identified and marked with red and blue respectively.


Line 138: Line 199:


Remember, this script will flush your existing iptables rules (UFW included), therefore you need to append your own rules into this script if you need any additional firewall rules.
Remember, this script will flush your existing iptables rules (UFW included), therefore you need to append your own rules into this script if you need any additional firewall rules.
 
<syntaxhighlight lang="bash">
#! /bin/bash
#! /bin/bash
# Niftiest Software – www.niftiestsoftware.com
# Niftiest Software – www.niftiestsoftware.com
Line 181: Line 242:


exit 0
exit 0
</syntaxhighlight>
Hit Ctrl+X, Y and Enter to save and exit.
Hit Ctrl+X, Y and Enter to save and exit.


Make the iptables script executable
Make the iptables script executable
 
<syntaxhighlight lang="bash">
sudo chmod +x /etc/openvpn/iptables.sh
sudo chmod +x /etc/openvpn/iptables.sh
Routing Rules Script for the Marked Packets
</syntaxhighlight>
====Routing Rules Script for the Marked Packets====
With the routing rules we configure the route for the packets we just marked with the first script. You can read more about the routing tables at the following link.
With the routing rules we configure the route for the packets we just marked with the first script. You can read more about the routing tables at the following link.


Create the routing script
Create the routing script
 
<syntaxhighlight lang="bash">
sudo nano /etc/openvpn/routing.sh
sudo nano /etc/openvpn/routing.sh
</syntaxhighlight>
Paste the following script which makes the default route after the VPN the loopback interface, effectively nulling the traffic if the VPN connection goes down.
Paste the following script which makes the default route after the VPN the loopback interface, effectively nulling the traffic if the VPN connection goes down.
 
<syntaxhighlight lang="bash">
#! /bin/bash
#! /bin/bash
# Niftiest Software – www.niftiestsoftware.com
# Niftiest Software – www.niftiestsoftware.com
Line 212: Line 276:


exit 0
exit 0
</syntaxhighlight>
Hit Ctrl+X, Y and Enter to Save and Exit.
Hit Ctrl+X, Y and Enter to Save and Exit.


Finally, make the script executable
Finally, make the script executable
 
<syntaxhighlight lang="bash">
sudo chmod +x /etc/openvpn/routing.sh
sudo chmod +x /etc/openvpn/routing.sh
Configure Split Tunnel VPN Routing
</syntaxhighlight>
====Configure Split Tunnel VPN Routing====
We will need a routing table by adding the table name to the rt_tables file (in our case it is vpn). Open rt_tables
We will need a routing table by adding the table name to the rt_tables file (in our case it is vpn). Open rt_tables
 
<syntaxhighlight lang="bash">
sudo nano /etc/iproute2/rt_tables
sudo nano /etc/iproute2/rt_tables
Add the vpn user table at the bottom of the file
</syntaxhighlight>
 
Add the vpn user table at the bottom of the file:
<syntaxhighlight lang="bash">
200    vpn
200    vpn
</syntaxhighlight>
It should look similar to this:
It should look similar to this:
 
<syntaxhighlight lang="bash">
#
#
# reserved values
# reserved values
Line 238: Line 306:
#1      inr.ruhep
#1      inr.ruhep
200    vpn
200    vpn
</syntaxhighlight>
Hit Ctrl + X, Y and Enter to save and exit.
Hit Ctrl + X, Y and Enter to save and exit.


Change Reverse Path Filtering
====Change Reverse Path Filtering====
Finally, we need to change the default level of reverse path filtering to ensure the kernel routes the traffic correctly. By default it is set to value of 1 that is “strict mode”. It is not necessary to disable reverse path filtering completely (setting to “0”), but we need to set it to level 2, “loose mode”.
Finally, we need to change the default level of reverse path filtering to ensure the kernel routes the traffic correctly. By default it is set to value of 1 that is “strict mode”. It is not necessary to disable reverse path filtering completely (setting to “0”), but we need to set it to level 2, “loose mode”.


Create a reverse path filter file for the vpn user
Create a reverse path filter file for the vpn user
 
<syntaxhighlight lang="bash">
sudo nano /etc/sysctl.d/9999-vpn.conf
sudo nano /etc/sysctl.d/9999-vpn.conf
Copy the following, make sure you use the correct network interface name in the third line marked with red (remember the ip route list command from before and the output, in our case it was eth0)
</syntaxhighlight>
 
Copy the following, make sure you use the correct network interface name in the third line (remember the ip route list command from before and the output, in our case it was eth0)
<syntaxhighlight lang="bash">
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2
</syntaxhighlight>
Hit Ctrl + X, Y and Enter to save and exit.
Hit Ctrl + X, Y and Enter to save and exit.


To apply new sysctl rules run:
To apply new sysctl rules run:
 
<syntaxhighlight lang="bash">
sudo sysctl --system
sudo sysctl --system
Testing the VPN Split Tunnel
</syntaxhighlight>
===Testing the VPN Split Tunnel===
I recommend a system restart, and if everything was configured properly, you should have a running OpenVPN service enabled for the vpn user and all the other users on your server should have direct access to Internet. Now lets check if everything is correct.
I recommend a system restart, and if everything was configured properly, you should have a running OpenVPN service enabled for the vpn user and all the other users on your server should have direct access to Internet. Now lets check if everything is correct.


Test OpenVPN service
====Test OpenVPN service====
Login as your regular user over SSH, and check OpenVPN service status
Login as your regular user over SSH, and check OpenVPN service status
 
<syntaxhighlight lang="bash">
sudo systemctl status openvpn@openvpn.service
sudo systemctl status openvpn@openvpn.service
This should return something like this
</syntaxhighlight>
 
This should return something like this:
<syntaxhighlight lang="bash">
openvpn@openvpn.service - OpenVPN connection to client
openvpn@openvpn.service - OpenVPN connection to client
  Loaded: loaded (/etc/systemd/system/openvpn@openvpn.service; enabled; vendor preset: enabled)
  Loaded: loaded (/etc/systemd/system/openvpn@openvpn.service; enabled; vendor preset: enabled)
Line 278: Line 352:
Sep 05 11:25:21 server ovpn-client[3266]: OPTIONS IMPORT: route options modified
Sep 05 11:25:21 server ovpn-client[3266]: OPTIONS IMPORT: route options modified
Sep 05 11:25:21 server ovpn-client[3266]: OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Sep 05 11:25:21 server ovpn-client[3266]: OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
</syntaxhighlight>
Systemd gives a very nice overview about the service state. In the above example you can see that the service is Active (running), just as we need.
Systemd gives a very nice overview about the service state. In the above example you can see that the service is Active (running), just as we need.


If the service is not running you can check if there is a log of the error in /var/log/syslog . For troubleshooting you can set output verbosity in the openvpn.conf file to a higher level. Set it to 3 and check the syslog again. You can always ask for help in the forum section. Remember to set verbosity level back to 1 if you don't need more detailed logs anymore.
If the service is not running you can check if there is a log of the error in /var/log/syslog . For troubleshooting you can set output verbosity in the openvpn.conf file to a higher level. Set it to 3 and check the syslog again. Remember to set verbosity level back to 1 if you don't need more detailed logs anymore.


Check IP address
====Check IP address====
Using the SSH session for the regular user, check the IP address
Using the SSH session for the regular user, check the IP address
 
<syntaxhighlight lang="bash">
curl ipinfo.io
curl ipinfo.io
</syntaxhighlight>
It will return your IP and depending on how much information is provided, the country should be listed in each case. Obviously, it should be your ISP now and your location.
It will return your IP and depending on how much information is provided, the country should be listed in each case. Obviously, it should be your ISP now and your location.


Now check the IP address of the vpn user with
Now check the IP address of the vpn user with
 
<syntaxhighlight lang="bash">
sudo -u vpn -i -- curl ipinfo.io
sudo -u vpn -i -- curl ipinfo.io
</syntaxhighlight>
If everything went fine, it should return the IP address and the country of the VPN server you selected. If you used Sweden server, then the country should be “SE”. It is very important that the IP address for user vpn should be different then your regular user's IP.
If everything went fine, it should return the IP address and the country of the VPN server you selected. If you used Sweden server, then the country should be “SE”. It is very important that the IP address for user vpn should be different then your regular user's IP.


In my case for user vpn and using Sweden PIA server I have the following output
In my case for user vpn and using Sweden PIA server I have the following output
 
<syntaxhighlight lang="bash">
{
{
   "ip": "X.XXX.XXX.XX",
   "ip": "X.XXX.XXX.XX",
Line 303: Line 381:
   "loc": "59.3294,18.0686",
   "loc": "59.3294,18.0686",
   "org": "AS57858 Inter Connects Inc"
   "org": "AS57858 Inter Connects Inc"
</syntaxhighlight>
Obviously, the “x.xxx.xxx.xx” part is my assigned VPN IP address which is different then my public IP, and you can see the country as SE which is Sweden.
Obviously, the “x.xxx.xxx.xx” part is my assigned VPN IP address which is different then my public IP, and you can see the country as SE which is Sweden.


Check DNS Server
====Check DNS Server====
Finally, check if the DNS for VPN is properly configured, type
Finally, check if the DNS for VPN is properly configured, type
 
<syntaxhighlight lang="bash">
sudo -u vpn -i -- cat /etc/resolv.conf
sudo -u vpn -i -- cat /etc/resolv.conf
</syntaxhighlight>
The output should be
The output should be
 
<syntaxhighlight lang="bash">
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
Line 316: Line 396:
nameserver 209.222.18.218
nameserver 209.222.18.218
nameserver 8.8.8.8
nameserver 8.8.8.8
</syntaxhighlight>
If you see the above DNS servers then your DNS for VPN is configured correctly.
If you see the above DNS servers then your DNS for VPN is configured correctly.


Line 326: Line 407:


Edit openvpn.conf to remove update-resolv-conf from up call
Edit openvpn.conf to remove update-resolv-conf from up call
 
<syntaxhighlight lang="bash">
sudo nano /etc/openvpn/openvpn.conf
sudo nano /etc/openvpn/openvpn.conf
</syntaxhighlight>
Locate the line down /etc/openvpn/update-resolv-conf and disable this line by putting a # at the beginning. Should look like this:
Locate the line down /etc/openvpn/update-resolv-conf and disable this line by putting a # at the beginning. Should look like this:
 
<syntaxhighlight lang="bash">
# down /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
</syntaxhighlight>
Hit Ctrl+X, Y and Enter to Save and Exit.
Hit Ctrl+X, Y and Enter to Save and Exit.


Next edit routing.sh script, where we will disable the call for update-resolv-conf
Next edit routing.sh script, where we will disable the call for update-resolv-conf
 
<syntaxhighlight lang="bash">
sudo nano /etc/openvpn/routing.sh
sudo nano /etc/openvpn/routing.sh
</syntaxhighlight>
Locate the line (should be at the end of the script): /etc/openvpn/update-resolv-conf and put a # at the beginning of the line. Should look like this:
Locate the line (should be at the end of the script): /etc/openvpn/update-resolv-conf and put a # at the beginning of the line. Should look like this:
 
<syntaxhighlight lang="bash">
# run update-resolv-conf script to set VPN DNS
# run update-resolv-conf script to set VPN DNS
# /etc/openvpn/update-resolv-conf
# /etc/openvpn/update-resolv-conf
</syntaxhighlight>
Hit Ctrl+X, Y and Enter to Save and Exit.
Hit Ctrl+X, Y and Enter to Save and Exit.


You can leave out the Configure VPN DNS Servers to Stop DNS Leaks section, if you didn't already complete it. If yes, no problem, as we will not use update-resolv-conf at all, we just disabled the calling of the script.
You can leave out the Configure VPN DNS Servers to Stop DNS Leaks section, if you didn't already complete it. If yes, no problem, as we will not use update-resolv-conf at all, we just disabled the calling of the script.


Configure Static IP for Your Server
====Configure Static IP for Your Server====
This part is actually something you should already have configured when you installed your server, as you need to configure the IP address, netmask and gateway here. Please use the instructions from your VPS provider or ISP on how to do this (if it is not automatically done for you, as with many VPS).
This part is actually something you should already have configured when you installed your server, as you need to configure the IP address, netmask and gateway here. Please use the instructions from your VPS provider or ISP on how to do this (if it is not automatically done for you, as with many VPS).


Line 350: Line 435:


Edit interfaces
Edit interfaces
 
<syntaxhighlight lang="bash">
sudo nano /etc/network/interfaces
sudo nano /etc/network/interfaces
</syntaxhighlight>
You should see something like this, where address, netmask and gateway should be already filled.
You should see something like this, where address, netmask and gateway should be already filled.
 
<syntaxhighlight lang="bash">
# Loopback device:
# Loopback device:
auto lo
auto lo
Line 365: Line 451:
  netmask  255.255.255.224
  netmask  255.255.255.224
  gateway  5.X.XXX.XXX  
  gateway  5.X.XXX.XXX  
</syntaxhighlight>
Here you need to add the DNS server line after the gateway entry, should look like this (don't change anything else). Remember, you can use other DNS servers, but make sure you use one that you trust.
Here you need to add the DNS server line after the gateway entry, should look like this (don't change anything else). Remember, you can use other DNS servers, but make sure you use one that you trust.
 
<syntaxhighlight lang="bash">
# Loopback device:
# Loopback device:
auto lo
auto lo
Line 379: Line 466:
  gateway  5.X.XXX.XXX
  gateway  5.X.XXX.XXX
  dns-nameservers 209.222.18.222 209.222.18.218 8.8.8.8
  dns-nameservers 209.222.18.222 209.222.18.218 8.8.8.8
</syntaxhighlight>
Hit Ctrl+X, Y and Enter to Save and Exit.
Hit Ctrl+X, Y and Enter to Save and Exit.



Latest revision as of 00:20, 4 March 2022

Force Torrent Traffic through VPN Split Tunnel Debian 8 + Ubuntu 16.04

It is very important to protect your online privacy. We would certainly recommend using a VPN (Virtual Private Network) with OpenVPN. Luckily, there are many paid VPN servers available with excellent performance at great price. Always read their Privacy Policy, consider the quality of the service for the price and choose one you trust. In this guide we will use Private Internet Access (PIA) as the VPN provider, in my experience configuring others will not differ too much.

Important: This guide is written for Ubuntu Server 16.04 LTS and Debian 8 systems (like Minibian, Raspbian, Bananian) that uses systemd services. It might work on other Linux distributions, but it is guaranteed to work on Ubuntu Server 16.04 LTS and Debian 8. For systems that use upstart script (like Ubuntu Server 14.04 LTS), upstart scripts are required instead of systemd service. If you are using Ubuntu Server 14.04 LTS, jump to the Force Torrent Traffic VPN Split Tunnel Ubuntu 14.04 guide.

The sections which are marked Minibian are needed only if you are, well, running Minibian. Ubuntu Server 16.04 LTS users should skip those parts (it will be always indicated in the relevant section).

Why Split VPN Tunnel?

If you are running a home server based on Ubuntu Server and you configure your OpenVPN client, you will be completely tunneled over the active VPN connection. But what if we would like to tunnel only few applications' traffic over VPN (for example Transmission or Deluge) and allow everything else direct connection? This is called split tunneling the VPN connection. What if your VPN connection breaks because the VPN server is offline? Without proper firewall rules you will automatically fall back to your direct Internet connection and immediately expose your real IP address. This poses privacy and anonymity risks!

The Benefits of VPN Split Tunneling

Control

You can select which services/applications should be tunneled over the VPN connection by running the selected services/application as vpn user, therefore you can protect your identity.

Automation

The VPN connection with Split Tunneling is started automatically on each system start, restarted automatically once the VPN provider is online again.

Increased Safety

If the VPN connection breaks, the vpn user is “disconnected” from the Internet (Automatic Kill Switch), if VPN connection is established again, vpn user will have access to Internet again over VPN. This ensures that your real IP address is never exposed publicly, only the IP address assigned by VPN provider is visible.

Increased Convenience

You retain you direct internet connection for all the other users, bypassing the VPN for services/applications that don't require you to hide your real IP address

Keep Remote Access

You will still be able to remotely manage your services by reverse proxy!

Installation Overview

This is an advanced guide but every effort has been made to make it friendly for new users with basic Linux knowledge. Should anything go wrong, feel free to comment or post on the Forum, we will do our best to help you. Since the publication of the VPN Split Tunnel guide for Ubuntu Server 14.04 LTS there are many interesting posts in the forum section.

This is Part 1 of the split tunnel guide. In this guide you will create and configure the vpn user.

In Part 2 of upcoming guides you will configure your torrent client (Transmission or Deluge) to run as the VPN user.

Here is an overview of all the steps in Part 1:

Install and configure OpenVPN (including auto connecting to VPN server on system start) Modify PIA configuration file to adjust for Split Tunneling Configure DNS Server for VPN connection to prevent DNS leak Create the vpn user that will be tunneled over VPN Use iptables to mark vpn user's traffic and routing rules to route marked packets over VPN connection Check everything is configured and working correctly

Install openvpn

fortunately, the Ubuntu and Debian repositories are not always up to date. It is recommended to use the latest OpenVPN release to make sure you have the latest security fixes (and possible updates). In case of Ubuntu Server 16.04 the official OpenVPN repository always provides the latest version. In case of ARM CPUs like the Rasperry Pi running Raspbian or Minibian, we need to build the latest version since the OpenVPN repository doesn't provide builds for ARM based devices. It is quite easy to build OpenVPN from source (stay tuned for the guide), until then, on Debian, Minibian and Raspbian you can use the version available in the Debian repository.

Install OpenVPN on Ubuntu Server 16.04 LTS If you are using Ubuntu Server 16.04 LTS we will install OpenVPN from the official OpenVPN repository. First import the public GPG key that is used to sign the packages.

wget https://swupdate.openvpn.net/repos/repo-public.gpg -O - | sudo apt-key add - Add the OpenVPN repository

echo "deb http://build.openvpn.net/debian/openvpn/stable xenial main" | sudo tee -a /etc/apt/sources.list.d/openvpn.list Install OpenVPN

sudo apt-get update sudo apt-get install openvpn -y Update: OpenVPN apt repository has changed, the guide has been updated with the new address.

Install OpenVPN on Debian 8 (Minibian, Raspbian) Since OpenVPN repository doesn't support ARM based devices, we have two options. Use the OpenVPN version available in the Debian repository (probably quite outdated version), or build the latest OpenVPN version from source following our guide. I strongly recommend to build OpenVPN to get the latest version. If you decide to build OpenVPN from source, then skip the below two lines.

This will install OpenVPN from the Debian repository (required only if you didn't build OpenVPN from source)

apt-get update apt-get install openvpn -y create systemd service file for openvpn

sudo nano /etc/systemd/system/openvpn@openvpn.service
[Unit]
Description=OpenVPN connection to %i
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
After=network.target

[Service]
RuntimeDirectory=openvpn
PrivateTmp=true
KillMode=mixed
Type=forking
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --config /etc/openvpn/%i.conf --writepid /run/openvpn/%i.pid
PIDFile=/run/openvpn/%i.pid
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/etc/openvpn
Restart=on-failure
RestartSec=3
ProtectSystem=yes
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw

[Install]
WantedBy=multi-user.target

make sure the following are installed:

apt-get install nano sudo apt-utils iptables curl resolvconf unzip

Configure VPN DNS Servers to Stop DNS Leaks

Next we are going to prevent DNS leak. DNS Leaks are often the main reason your real identity gets exposed even if using VPN. You can read more about DNS leaks here and test them here. The update-resolv-conf script that comes with OpenVPN will automatically apply the preferred DNS servers when OpenVPN connects.

This script will make sure that when using OpenVPN you are not subject to DNS leaks. We will use Openvpn's DNS Servers (208.67.222.222 and 208.67.220.220) and Google's (8.8.8.8) as a third option. You are free to use the DNS servers you trust and prefer. It is advised to change the local DNS to a public even if you are not using VPN. If you are behind a router (and you probably are), it is also a good practice to configure public DNS address on the router too.

Note: make sure you are using a static IP on your machine or reserved DHCP also known as static DHCP. Do not configure the static IP on your server, as resolvconf will not work then. You should set the static IP from your router!

Open the update-resolv-conf file

sudo nano /etc/openvpn/update-resolv-conf

Locate this part:

# foreign_option_1='dhcp-option DNS 193.43.27.132'
# foreign_option_2='dhcp-option DNS 193.43.27.133'
# foreign_option_3='dhcp-option DOMAIN be.bnc.ch'

Replace the part highlighted in red, make sure you uncomment (remove the # from beginning) these 3 lines, and pay attention to the third line where your need to replace DOMAIN with DNS.

It should look exactly like this:

foreign_option_1='dhcp-option DNS 208.67.222.222'
foreign_option_2='dhcp-option DNS 208.67.220.220'
foreign_option_3='dhcp-option DNS 8.8.8.8'

Hit Ctrl+X, Y and Enter to Save.

Your DNS is configured for OpenVPN to prevent DNS leaks.

Split Tunneling with iptables and Routing Tables

We will use iptables to mark packets from a user (in our case the vpn user), and then use routing tables to route these marked packets through the OpenVPN interface, while allowing unmarked packets direct access to the Internet.

Create vpn User Create the user vpn. All of the applications you want tunneled over VPN will run as this user, especially your torrent client of choice (Transmission or Deluge). At the end of this guide you will see the links to our guides on how to configure Transmission and Deluge with Split Tunneling.

Create vpn user with no login option

sudo adduser --disabled-login vpn

I suggest to leave personal details blank, just proceed with Enter, and finally answer Y to create vpn user. We disabled login for the vpn user for security reasons, there is no need to log in to the system as the vpn user.

We are going to use the vpn user to run services (like Torrent client), it is recommended to add your regular user to the vpn group and vpn user to your regular user's group to avoid any permission issues.

Replace username with the user you would like to add to the vpn group

sudo usermod -aG vpn username

Replace group with the group name of your regular user that you would like to add the vpn user to

sudo usermod -aG group vpn

The iptables Script

We need the local IP and the name of the network interface. Again, make sure you are using a static IP on your machine or reserved DHCP also known as static DHCP, but configured on your router!

ip route list

The output will be similar to this:

default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.110

eth0 is the network interface (NETIF), and 192.168.1.110 is the local IP address (LOCALIP). You will need to enter these two into the following script, which we are going to create now.

UPDATE (8 November 2016)

Thanks to a feedback by our member Jesus, we are now addressing a vulnerability related to the VPN Split Tunnel implementation. If the PIA login credentials are not correct, then OpenVPN will not establish the VPN connection, therefore the firewall rules are not applied (since OpenVPN will execute up scripts only on successful connection). The result is not having the kill switch enabled (iptables rules loaded) and vpn user has direct access to Internet. To prevent this scenario, we will implement a permanent firewall rule to block vpn user’s access to Internet until the OpenVPN tunnel is up and functional, and the required scripts are started. This will prevent any IP leaks even if no connection to PIA is possible for any reason.

Flush current iptables rules

sudo iptables -F

Add the following rule, which will block vpn user's access to Internet (except the loopback device). Note, if you configured Split Tunnel with different user then vpn, then change vpn marked in red to the user you used.

sudo iptables -A OUTPUT ! -o lo -m owner --uid-owner vpn -j DROP

Now install iptables-persistent to save this single rule that will be always applied on each system start.

sudo apt-get install iptables-persistent -y

During the install, iptables-persistent will ask you to save current iptables rules to /etc/iptables/rules.v4 as seen on the screenshot, accept this with YES

Now when system starts, vpn user is not able to access Internet. If the OpenVPN service is started successfully, then this rule is flushed (only until the next system restart), and the Split Tunnel rules are applied.

iptables Script for vpn User

The first script will mark the packets for vpn user, the second script will take care of proper routing.

Create the iptables script

sudo nano /etc/openvpn/iptables.sh

Copy the following to the iptables.sh script, and make sure you enter the network interface and the local IP we identified and marked with red and blue respectively.

You can see the comments for each section about the function of the given part of the script. If you are interested in more details about iptables, a good starting point is the Official Ubuntu Documentation.

Remember, this script will flush your existing iptables rules (UFW included), therefore you need to append your own rules into this script if you need any additional firewall rules.

#! /bin/bash
# Niftiest Software – www.niftiestsoftware.com
# Modified version by HTPC Guides – www.htpcguides.com

export INTERFACE="tun0"
export VPNUSER="vpn"
export LOCALIP="192.168.1.110"
export NETIF="eth0"

# flushes all the iptables rules, if you have other rules to use then add them into the script
iptables -F -t nat
iptables -F -t mangle
iptables -F -t filter

# mark packets from $VPNUSER
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT ! --dest $LOCALIP -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT --dest $LOCALIP -p udp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT --dest $LOCALIP -p tcp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT ! --src $LOCALIP -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT -j CONNMARK --save-mark

# allow responses
iptables -A INPUT -i $INTERFACE -m conntrack --ctstate ESTABLISHED -j ACCEPT

# block everything incoming on $INTERFACE to prevent accidental exposing of ports
iptables -A INPUT -i $INTERFACE -j REJECT

# let $VPNUSER access lo and $INTERFACE
iptables -A OUTPUT -o lo -m owner --uid-owner $VPNUSER -j ACCEPT
iptables -A OUTPUT -o $INTERFACE -m owner --uid-owner $VPNUSER -j ACCEPT

# all packets on $INTERFACE needs to be masqueraded
iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE

# reject connections from predator IP going over $NETIF
iptables -A OUTPUT ! --src $LOCALIP -o $NETIF -j REJECT

# Start routing script
/etc/openvpn/routing.sh

exit 0

Hit Ctrl+X, Y and Enter to save and exit.

Make the iptables script executable

sudo chmod +x /etc/openvpn/iptables.sh

Routing Rules Script for the Marked Packets

With the routing rules we configure the route for the packets we just marked with the first script. You can read more about the routing tables at the following link.

Create the routing script

sudo nano /etc/openvpn/routing.sh

Paste the following script which makes the default route after the VPN the loopback interface, effectively nulling the traffic if the VPN connection goes down.

#! /bin/bash
# Niftiest Software – www.niftiestsoftware.com
# Modified version by HTPC Guides – www.htpcguides.com

VPNIF="tun0"
VPNUSER="vpn"
GATEWAYIP=$(ifconfig $VPNIF | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | egrep -v '255|(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' | tail -n1)
if [[ `ip rule list | grep -c 0x1` == 0 ]]; then
ip rule add from all fwmark 0x1 lookup $VPNUSER
fi
ip route replace default via $GATEWAYIP table $VPNUSER
ip route append default via 127.0.0.1 dev lo table $VPNUSER
ip route flush cache

# run update-resolv-conf script to set VPN DNS
/etc/openvpn/update-resolv-conf

exit 0

Hit Ctrl+X, Y and Enter to Save and Exit.

Finally, make the script executable

sudo chmod +x /etc/openvpn/routing.sh

Configure Split Tunnel VPN Routing

We will need a routing table by adding the table name to the rt_tables file (in our case it is vpn). Open rt_tables

sudo nano /etc/iproute2/rt_tables

Add the vpn user table at the bottom of the file:

200     vpn

It should look similar to this:

#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
#1      inr.ruhep
200     vpn

Hit Ctrl + X, Y and Enter to save and exit.

Change Reverse Path Filtering

Finally, we need to change the default level of reverse path filtering to ensure the kernel routes the traffic correctly. By default it is set to value of 1 that is “strict mode”. It is not necessary to disable reverse path filtering completely (setting to “0”), but we need to set it to level 2, “loose mode”.

Create a reverse path filter file for the vpn user

sudo nano /etc/sysctl.d/9999-vpn.conf

Copy the following, make sure you use the correct network interface name in the third line (remember the ip route list command from before and the output, in our case it was eth0)

net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2

Hit Ctrl + X, Y and Enter to save and exit.

To apply new sysctl rules run:

sudo sysctl --system

Testing the VPN Split Tunnel

I recommend a system restart, and if everything was configured properly, you should have a running OpenVPN service enabled for the vpn user and all the other users on your server should have direct access to Internet. Now lets check if everything is correct.

Test OpenVPN service

Login as your regular user over SSH, and check OpenVPN service status

sudo systemctl status openvpn@openvpn.service

This should return something like this:

openvpn@openvpn.service - OpenVPN connection to client
 Loaded: loaded (/etc/systemd/system/openvpn@openvpn.service; enabled; vendor preset: enabled)
 Active: active (running) since Mon 2016-09-05 11:25:18 CEST; 1 day 4h ago
 Docs: man:openvpn(8)
 https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
 https://community.openvpn.net/openvpn/wiki/HOWTO
 Process: 3223 ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn
 Main PID: 3266 (openvpn)
 CGroup: /system.slice/system-openvpn.slice/openvpn@openvpn.service
 └─3266 /usr/sbin/openvpn --daemon ovpn-client --status /run/openvpn/client.status 10 --cd /etc/openvpn

Sep 05 11:25:21 server ovpn-client[3266]: OPTIONS IMPORT: route options modified
Sep 05 11:25:21 server ovpn-client[3266]: OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified

Systemd gives a very nice overview about the service state. In the above example you can see that the service is Active (running), just as we need.

If the service is not running you can check if there is a log of the error in /var/log/syslog . For troubleshooting you can set output verbosity in the openvpn.conf file to a higher level. Set it to 3 and check the syslog again. Remember to set verbosity level back to 1 if you don't need more detailed logs anymore.

Check IP address

Using the SSH session for the regular user, check the IP address

curl ipinfo.io

It will return your IP and depending on how much information is provided, the country should be listed in each case. Obviously, it should be your ISP now and your location.

Now check the IP address of the vpn user with

sudo -u vpn -i -- curl ipinfo.io

If everything went fine, it should return the IP address and the country of the VPN server you selected. If you used Sweden server, then the country should be “SE”. It is very important that the IP address for user vpn should be different then your regular user's IP.

In my case for user vpn and using Sweden PIA server I have the following output

{
  "ip": "X.XXX.XXX.XX",
  "hostname": "No Hostname",
  "city": "",
  "region": "",
  "country": "SE",
  "loc": "59.3294,18.0686",
  "org": "AS57858 Inter Connects Inc"

Obviously, the “x.xxx.xxx.xx” part is my assigned VPN IP address which is different then my public IP, and you can see the country as SE which is Sweden.

Check DNS Server

Finally, check if the DNS for VPN is properly configured, type

sudo -u vpn -i -- cat /etc/resolv.conf

The output should be

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 209.222.18.222
nameserver 209.222.18.218
nameserver 8.8.8.8

If you see the above DNS servers then your DNS for VPN is configured correctly.

UPDATE (July 15 2019): How to Configure with Static IP Many users reported problems using Split Tunnel when using static IP configured on Ubuntu Server 16.04 or Debian 8. I did some testing, and for static IP systems I would recommend to use the following configuration.

A note on static IP and is this update needed for your setup: by static IP I mean if the Ubuntu Server or Debian installation is configured with static IP in network interfaces (like some of the VPS providers), and NOT that you have set a static IP from your router to your server! The later is called static DHCP or DHCP reservation, when your server is configured as DHCP; your router always assigns the same IP address to a specific computer on your LAN (put it simply: the router's DHCP function assigns the static IP to the unique MAC address of the server's NIC). If you are using static DHCP or DHCP reservation, then you should complete the steps in the guide, and not use the below workaround.

If you need to enter IP, Netmask and Gateway on your server, then you need to use this method described in this section. The main difference compared to the method described in the guide is that we will not use update-resolv-conf for DNS, but configure the two primary DNS servers of PIA, and the third DNS server of Google in the network interfaces. Proceed as following:

Edit openvpn.conf to remove update-resolv-conf from up call

sudo nano /etc/openvpn/openvpn.conf

Locate the line down /etc/openvpn/update-resolv-conf and disable this line by putting a # at the beginning. Should look like this:

# down /etc/openvpn/update-resolv-conf

Hit Ctrl+X, Y and Enter to Save and Exit.

Next edit routing.sh script, where we will disable the call for update-resolv-conf

sudo nano /etc/openvpn/routing.sh

Locate the line (should be at the end of the script): /etc/openvpn/update-resolv-conf and put a # at the beginning of the line. Should look like this:

# run update-resolv-conf script to set VPN DNS
# /etc/openvpn/update-resolv-conf

Hit Ctrl+X, Y and Enter to Save and Exit.

You can leave out the Configure VPN DNS Servers to Stop DNS Leaks section, if you didn't already complete it. If yes, no problem, as we will not use update-resolv-conf at all, we just disabled the calling of the script.

Configure Static IP for Your Server

This part is actually something you should already have configured when you installed your server, as you need to configure the IP address, netmask and gateway here. Please use the instructions from your VPS provider or ISP on how to do this (if it is not automatically done for you, as with many VPS).

What we need to do here is to add a DNS entry to make sure the system is using the PIA DNS servers and the third server from Google. Remember, it is very important to use a DNS server you trust, and I would suggest against of using the DNS servers of your ISP.

Edit interfaces

sudo nano /etc/network/interfaces

You should see something like this, where address, netmask and gateway should be already filled.

# Loopback device:
auto lo
iface lo inet loopback
iface lo inet6 loopback

# device: eth0
auto  eth0
iface eth0 inet static
 address   5.X.XXX.XXX 
 netmask   255.255.255.224
 gateway   5.X.XXX.XXX

Here you need to add the DNS server line after the gateway entry, should look like this (don't change anything else). Remember, you can use other DNS servers, but make sure you use one that you trust.

# Loopback device:
auto lo
iface lo inet loopback
iface lo inet6 loopback

# device: eth0
auto  eth0
iface eth0 inet static
 address   5.X.XXX.XXX 
 netmask   255.255.255.224
 gateway   5.X.XXX.XXX
 dns-nameservers 209.222.18.222 209.222.18.218 8.8.8.8

Hit Ctrl+X, Y and Enter to Save and Exit.

That's it, now do a system restart, and Split Tunnel should be working with DNS name resolution using secure DNS servers.

Sources

https://www.htpcguides.com/compile-latest-openvpn-from-source-on-debian-8/
https://www.htpcguides.com/force-torrent-traffic-vpn-split-tunnel-debian-8-ubuntu-16-04/