HOW TO: VPN for one application (or several)

Write tutorials for Linux Mint here
More tutorials on https://github.com/orgs/linuxmint/discu ... /tutorials and (archive) on https://community.linuxmint.com/tutorial
Forum rules
Don't add support questions to tutorials; start your own topic in the appropriate sub-forum instead. Before you post read forum rules
Locked
passerby

HOW TO: VPN for one application (or several)

Post by passerby »

Preamble

With the increasing amount of geoblocking, ISP website blocking, government monitoring, etc. the notion of using a VPN has become increasingly popular.
One drawback when using a VPN, however, is the fact that all of your traffic goes through it, not just one or two programs.

Of course, there are ways around this.
Some people just use a proxy instead, so as to hide their IP. Others run a VPN on a separate machine, or in a virtual machine.
But using a proxy only hides your IP, not the data transmitted, and running a VPN on its own machine or VM is overkill.

So, what else can we do? We can use the magic of multiple network interfaces, multiple users, and ip routing.
For reference (and googlers), this tactic is called split tunneling, and we're going to direct only specific applications through the VPN.

Forewarning

I'm not going to lecture you on not using split tunneling to torrent at work, hide your late night habits, etc. That's none of my business.

All I'm going to warn you about is that I'll be making extensive use of command line arguments, so don't expect screenshots and nice GUI applications.
This is because a) it's faster, b) the instructions will be exactly the same for different desktop environments, and c) not all of this can be done easily via a GUI.
You don't need to be an expert to follow this guide. For the most part you'll be able to copy and paste the commands provided. Just make sure you read the instructions, so you know which must be changed.

Also, you might want to keep a second OS or computer handy. You shouldn't run into any trouble if you follow the instructions exactly, but if you do make an error during the later stages, it's possible to block your own internet traffic, thus preventing you from googling the cure :lol:

Prerequisites

I believe Mint/Ubuntu come with most of what you need by default. The only package you should need is openvpn.

Code: Select all

sudo apt-get install openvpn
You'll also need a VPN to test this with. I have a subscription to PrivateInternetAccess, so I'll be using that.
Also, make sure you have the .ovpn file necessary. Your VPN provider should supply you with one.

Last but not least, you'll need root privileges. If you can sudo, you should be good.

And with that, we're ready to go...

Step 1: Create a new user

You don't need to do this if you have more than one user already, but I think it's best to have a single, specific user for what we're going to be doing.
Spoiler: every program run by this user will go through the VPN, and every program run by your current user will run through your normal network.

You can do this step via a GUI, but in the interest of making this as quick and desktop-neutral as possible, we'll use the terminal.

Code: Select all

sudo useradd -m vpn
You can name the user whatever you want, but given what we're doing, I think vpn is an appropriate name.

Step 2: OpenVPN config

Ready your .ovpn file, because it's time to do some editing.
Open the file in a text editor. The changes you'll need to make will depend on your config file.
First, let's take a look at mine.

Code: Select all

client
dev tun0
proto udp
remote swiss.privateinternetaccess.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca /home/passerby/.PIA/ca.crt
tls-client
remote-cert-tls server
auth-user-pass /home/passerby/.PIA/auth.conf
comp-lzo
verb 1
reneg-sec 0
crl-verify /home/passerby/.PIA/crl.pem

# Add these lines:
route-nopull
script-security 2
up /etc/openvpn/up.sh

#Extras
down /etc/openvpn/down.sh
inactive 300
ping 30
ping-exit 90
Yours may look very different to this. I don't know your provider or .ovpn configuration.
But in the above file, there are a few important lines. For the time being, you'll need route-nopull, script-security 2, and up /etc/openvpn/up.sh

route-nopull means the VPN won't pull in all of your internet traffic. It'll only use what you tell it to.
script-security 2 lets us run the next command.
up /etc/openvpn/up.sh runs up.sh upon successfully connecting to the VPN.

Step 3: Find your gateway IP

To get your default gateway, open another terminal and run the command

Code: Select all

echo -n $(ip route show | grep "default" | cut -d \  -f 3 | cut -d \. -f 1-3) && echo ".0/24"
This will grab your default gateway IP and replace the last number with "0/24". (This is a precaution for minor network ip changes)
Keep track of this IP address. You'll need it in the next step. In my case, the address is "192.168.1.0/24".

Step 4: Create up.sh

This isn't mandatory. You can also run these commands manually, if you really want to.
...But why would you want to do that?

Code: Select all

sudo nano /etc/openvpn/up.sh
(You can replace "nano" with whatever text editor you fancy)
The information you enter will change a little depending on the interface in your .ovpn file (mine was tun0) and your default gateway (from step 4).
With that information handy, enter the following:

Code: Select all

#!/bin/sh
iptables -t mangle -I OUTPUT -m owner --uid-owner vpn -j MARK --set-mark 42
iptables -t mangle -I OUTPUT -d 192.168.1.0/24 -m owner --uid-owner vpn -j RETURN
iptables -t nat -I POSTROUTING -o tun0 -j MASQUERADE
ip rule add fwmark 42 table 42

for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
    echo 0 > $f
    done;

ip route add default via $(ifconfig -a tun0 | grep -o 'P-t-P:[^ ]*' | cut -d : -f 2) table 42

chgrp vpn $XAUTHORITY
chmod 640 $XAUTHORITY
Replace 192.168.1.0/24 with your own address, assuming it's any different.
Also, replace the instances of "vpn" if you're using a different user, and replace tun0 if you're using a different interface.

Now that up.sh has been written, we need to make it executable.

Code: Select all

sudo chmod +x /etc/openvpn/up.sh
And we're done with up.sh.

Step 5: Start OpenVPN

All you'll need for this step is your .ovpn file from earlier.

Code: Select all

sudo openvpn --config '/home/passerby/Switzerland.ovpn' --setenv XAUTHORITY $XAUTHORITY
OpenVPN will start, attempting to apply the settings in your .ovpn file.
It will also run /etc/openvpn/up.sh, which will set up all of the necessary routing rules.
Once it outputs the text "Initialization Sequence Completed", you will be connected to the VPN.


And that's it! You're ready to run applications selectively through your VPN.
To test it out, open another terminal and run:

Code: Select all

DISPLAY=":0" XAUTHORITY=$XAUTHORITY sudo -u vpn -H firefox
replacing vpn with the user you want, and firefox with the program you want to run.
You should choose a browser that isn't running, then go to a website like http://www.myipaddress.com/what-is-my-ip-address/ to check if your IP is masked in the browser.
If it is, you've succeeded. Well done!

Future VPN setup

After you've run through these steps once, you'll only need to run step 5 again. In other words, the next time I want to connect, I would run:

Code: Select all

sudo openvpn --config '/home/passerby/Switzerland.ovpn' --setenv XAUTHORITY $XAUTHORITY
One line and split tunneling is enabled once more.

Extras

Remember my .ovpn file from earlier? There were a couple of tweaked settings down the bottom which you might be interested in.

Code: Select all

down /etc/openvpn/down.sh
inactive 300
ping 30
ping-exit 90
down is the opposite of up (duh). This script will run when your VPN is closing.
You can create it by following the same steps as for up.sh, but the commands you'll want to enter will be different.
For example, my down.sh file is:

Code: Select all

#!/bin/sh
killall --user vpn
This means that if OpenVPN closes, whether I make it close or it closes unexpectedly, every application being used by "vpn" will close as well. No data leaks for me, thank you!

inactive, ping and ping-exit are all used to check your connection to the VPN. All three values are measured in seconds.
inactive refers to how long it's been since any data was sent or received. If that much time passes without any activity, OpenVPN will close.
ping refers to how often we should attempt to ping the VPN server.
ping-exit is the number of seconds after which we should close OpenVPN if our pings haven't been successful.

By combining these four settings, we can protect ourselves from any data being leaked.
With the settings I've given above, openvpn will be killed if:
-none of the programs running in my VPN have sent or received any data for 5 minutes, or
-I've been unable to ping the VPN for 1.5 minutes
If this happens, or if I lose connection to the VPN for any reason whatsoever, every application being run as "vpn" will be killed, so they won't be able to continue running outside of the VPN.
Last edited by passerby on Sat Nov 15, 2014 7:28 pm, edited 4 times in total.
PatH57

Re: HOW TO: VPN for one application (or several)

Post by PatH57 »

nice and easy to follow.
like the script for disabling running apps if vpn is down.
passerby

Re: HOW TO: VPN for one application (or several)

Post by passerby »

Update: I've removed step 7 and added a new line to the end of the up.sh file.
This takes care of the final step for you, so to start split tunneling you only need to start openvpn; no need to enter any other commands afterwards.
teeedubb

Re: HOW TO: VPN for one application (or several)

Post by teeedubb »

Hi,

Thanks very much for this how to, it was exactly what I was after and the end result works great.

One question, do you know if it is possible to configure port forwarding via the method in this how-to for programs such as rtorrent? I've tried many different iptables rules to no avail and any help in getting port forwarding setup would be greatly appreciated.
r00t

Re: HOW TO: VPN for one application (or several)

Post by r00t »

The last reply to this thread was over a year ago! teeedubb, please create your own thread about your problem. Thread locked.
Locked

Return to “Tutorials”