OpenVPN Split Tunneling (specify apps that go through VPN tunnel)

Anyone new to this topic, just skip to this post

OLD POST:
Background:
I have been diving into options to run OpenVPN for apps that need it. The idea is that some applications like Torrent clients and torrent scrapers like Flexget, Sickrage, Sonarr etc would need to go via VPN (depending on the country you live in). While other applications like Kodi, SyncThing, BittorrentSync, OwnCloud etc etc gain nothing by going through your VPN. Actually their speed will most likely decrease. Also, for Kodi, you might not be able to watch certain content (like BBC) since it has geo restrictions. You might want a specific VPN geo for those things, which is an entirely different requirement for VPN compared to Torrents and would rather be a solution in the form of a Kodi addon allowing you to turn on/off VPN for Kodi and to select a GEO/VPN from your couch with your TV remote. I am really talking about non-Kodi, apps that allow you to get content. Most people will want those apps to go via VPN permanently.

Solution:
For those reasons, it does not make sense to me to simply run OpenVPN on my OSMC device (or router) and let all network traffic go through that VPN server. Therefore, I am looking into the best solution to have specific applications always access the internet via VPN. If VPN is down, the applications do not have internet access.

From my online research, the best way to do this is to run OpenVPN within a seperate network namespace and make sure the applications that need to go through VPN will run within that network namespace. The latter seems the easiest part. The first is the one I am having trouble with.
Once I have got this working, I will post a NOOB HowTo for everyone, which will change the OSMC service scripts that run for example Transmission in such a way it will always run via the namespace, integrating nicely with OSMC’s options to start/stop any app.

The solution I found is described at the bottom of this question:

And it is completely based on this: Running an OpenVPN tunnel inside a network namespace
But for easy reading, i am quoting the information from those websites:

1. First create an --up script for OpenVPN. This script will create the VPN tunnel interface inside a network namespace called vpn, instead of the default namespace.

#!/bin/sh
case $script_type in
        up)
                ip netns add vpn
                ip netns exec vpn ip link set dev lo up
                mkdir -p /etc/netns/vpn
                echo "nameserver 8.8.8.8" > /etc/netns/vpn/resolv.conf
                ip link set dev "$1" up netns vpn mtu "$2"
                ip netns exec vpn ip addr add dev "$1" \
                        "$4/${ifconfig_netmask:-30}" \
                        ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"}
                test -n "$ifconfig_ipv6_local" && \
          ip netns exec vpn ip addr add dev "$1" \
                        "$ifconfig_ipv6_local"/112
                ;;
        route-up)
                ip netns exec vpn ip route add default via "$route_vpn_gateway"
                test -n "$ifconfig_ipv6_remote" && \
          ip netns exec vpn ip route add default via \
                        "$ifconfig_ipv6_remote"
                ;;
        down)
                ip netns delete vpn
                ;;
esac

2. Then start OpenVPN and tell it to use our --up script instead of executing ifconfig and route.

openvpn --ifconfig-noexec --route-noexec --up netns-up --route-up netns-up --down netns-up

3. Now you can start programs to be tunneled like this:

ip netns exec vpn command

The only catch is that you need to be root to invoke ip netns exec … and maybe you do not want your application to run as root. The solution is simple:

sudo ip netns exec vpn sudo -u $(whoami) command

END OF QUOTE

Problem:
The problem I am having is with the script. When I run the command from step 2, this is my output:

:/etc/openvpn$ sudo openvpn --ifconfig-noexec --route-noexec --up netns-up --route-up netns-up --down netns-up --config za1.nordvpn.com.tcp443.ovpn
(..)

Tue Mar 22 00:10:56 2016 [vpn-za.nordvpn.com] Peer Connection Initiated with [AF_INET]154.127.61.142:443
Tue Mar 22 00:10:59 2016 SENT CONTROL [vpn-za.nordvpn.com]: 'PUSH_REQUEST' (status=1)
Tue Mar 22 00:10:59 2016 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1,dhcp-option DNS 78.46.223.24,dhcp-option DNS 162.242.211.137,route 10.7.7.1,topology net30,ping 5,ping-restart 30,ifconfig 10.7.7.102 10.7.7.101'
Tue Mar 22 00:10:59 2016 OPTIONS IMPORT: timers and/or timeouts modified
Tue Mar 22 00:10:59 2016 OPTIONS IMPORT: --ifconfig/up options modified
Tue Mar 22 00:10:59 2016 OPTIONS IMPORT: route options modified
Tue Mar 22 00:10:59 2016 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Tue Mar 22 00:10:59 2016 ROUTE_GATEWAY 192.168.1.254/255.255.255.0 IFACE=eth0 HWADDR=b8:27:eb:39:7e:46
Tue Mar 22 00:10:59 2016 TUN/TAP device tun0 opened
Tue Mar 22 00:10:59 2016 TUN/TAP TX queue length set to 100
Tue Mar 22 00:10:59 2016 netns-up tun0 1500 1592 10.7.7.102 10.7.7.101 init
Tue Mar 22 00:10:59 2016 WARNING: Failed running command (--up/--down): external program exited with error status: 1
Tue Mar 22 00:10:59 2016 Exiting due to fatal error

I tried to trace the error by executing the commands from the script listed under the “UP” case one by one. The following command seems to be incorrect:
sudo ip link set dev "$1" up netns vpn mtu "$2"
because it shows me how to use “IP LINK”, so clearly the command is using IP LINK incorrectly. I read about this command but I have no idea how to fix this so I am completely stuck.

I have posted this issue in the OpenVPN forum but to my suprise there has been little response. I tried replying on the stackexchange.com question, replying to the person with the answer at the bottom but I do not have enough credits to do so. I even created a whole new question on stackexchange with 0 response. I hope someone with Linux network experience can help me out here.

bump!

hey zilexa, I’ve been into similar problem myself and I’ve seen your posts.
Today I was able to make it work for me.
Although I think it’s not the best solution, but it’s the working one, so, here’s my latest history.

ip netns add ns2
ip link add vns2a type veth peer name vns2b
ip link set vns2b netns ns2
ip netns exec ns2 ifconfig vns2b 10.1.2.1/24 up
ifconfig vns2a 10.1.2.2/24 up
ping 10.1.2.1
ip link set tun0 netns ns2
ip netns exec ns2 ip link set tun0 up
ip netns exec ns2 ip addr add 10.10.0.6/24 dev tun0 # I set /24 network so that I could do the next step
ip netns exec ns2 ip route add default via 10.10.0.5
ip netns exec ns2 ping 8.8.8.8
ip netns exec ns2 ping google.com # would not work yet, we need to set dns so…
mkdir -p /etc/netns/ns2
echo “nameserver 8.8.8.8” > /etc/netns/ns2/resolv.conf
echo “nameserver 8.8.4.4” > /etc/netns/ns2/resolv.conf
ip netns exec ns2 ping google.com # should work great
ip netns exec ns2 wget http://icanhazip.com -qO- # should return your vpn ip

I did it while openvpn service was running.
I’m not sure if it will remain after reboot.

Wow thanks, I am already happy someone with more expertise on this matter has replied.

I found these two solutions a few days ago but I did not have the time to play with it. I think you will like the first one a lot.

  1. This person explains every step and clearly says he has based it on the solution in my first post, same as you, but he has probably perfected it and made it to work after reboot:
    nsdo/openvpn-example.md at master · ausbin/nsdo · GitHub
    But I think it could be done with less scripts. The veth could perhaps be combined with the first script. No idea. This seems to be the best solution, since it even supports access to the WebUI of Transmission for example, even if Transmission is in the 2nd network namespace.

  2. vpn-netns/README.md at master · amonakov/vpn-netns · GitHub
    Not sure about this one.

Would love to hear your feedback.

I’m unsure how to even try the first approach…
I have no openvpn@.service file in /etc/systemd/system/.
I have one in /lib/systemd/system/ which looks like this:

[Unit]
Description=OpenVPN connection to %i
PartOf=openvpn.service
ReloadPropagatedFrom=openvpn.service

[Service]
Type=forking
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status$
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/etc/openvpn

[Install]
WantedBy=multi-user.target

And in /etc/systemd/system/multi-user.target.wants/openvpn.service
which looks like this:

[Unit]
Description=OpenVPN service
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true
WorkingDirectory=/etc/openvpn

[Install]
WantedBy=multi-user.target

Any news here? did anyone manage to get a network namespace with openvpn and other apps to work?

I will update later

Great, looking forward to this, I allready put thus shelved.

Well this can be implemented fairly easy by following each step correctly:

A few things were a bit vague, I emailed him and he replied swiftly so I could finish all steps last night. Unfortunately there is an error when I try to start the service. So I have to get in touch with him again.

This doesn’t sound like a good idea at all… I don’t think my vero2 could cope with “a bunch of” vpns running at the same time…It already seems to strugle with one instance because without vpn my dl speed is at 75mbit/s and with vpn on it’s at 20mbit/s (provider is not to blame cause on my pc via vpn I get full speed).
From vpn provider support I got told that it’s crucial how fast the cpu can process its cycles.
Or do you think it doesn’t matter as long as there aren’t multiple instances downloading at the same time?

Not sure why you are focusing on that sentence. It is not our goal nor is it the outcome of his example. But since you are isolating OpenVPN to limit it to certain programs, you could in theory run multiple at the same time. But I do not have a use case for that. Do you?

20mbit=2.5MB/s for my RPi3 I would consider 3MB/s the maximum (it is also the limit I set in Transmission). And I would be very happy to have that speed with OpenVPN. I was not aware the Vero2 could reach way higher speed.

I don’t care about download speeds since I don’t wait for downloads. They are scheduled automatically and finished by the time I want to watch something.

On topic: he replied again with some tips, what I might have done wrong but I don’t have time to eat again till tomorrow. Sorry!

Ok, so there can be multiple programs in one namespace under one vpn tunnel right? Guess I missunderstood that. Your’re maybe right concerning speed, but it bothers me that it’s just the device slowing it down. I tried with my router as a vpn client but speed was even worse.

@zilexa …digging this up again:
How’s your progress, did you actually manage to do what we want to? If yes, please tell me how. I have reinstalled osmc due to filesystem errors and not tried any of the approaches yet. Since I’m not good at these things I fear I can mess sth. up and end with no inet connection at all.

This looks very interesting, any update on the project?

Not really… Well, I ended up outsourcing the vpn stuff.
It really depends what you run on which device. Using openvpn client on my vero2 I couldn’t use my full bandwith (75 Mbps).
It was logical to let a router do the vpn work. After quite some reseach I bought a Linksys WRT1200ac router for 120€.
It was the “best bang for the buck” regarding other, way more expensive highend, gaming routers out there.
On it I installed ddwrt as firmware and it runs a openvpn client, with this router I’m capable of using my full bandwith.
I added a custom script that only lets my vero2 go trough vpn tunnel, all other devices connect “the normal way”.
I also tried to selectively route traffic by port on the vero2.
Like let all traffic from/to kodi go “the normal way” and all other stuff should go through vpn tunnel.
While the former did work, I’m unsure about the port routing…Streams via Kodi still buffer and lag more than without any vpn tunnel…

1 Like

Hi guys,

Digging the net for the same purpose I’ve found https://gist.github.com/JimboMonkey1234/1dfed632f6a45bb5f06bbb1c7eef770d. Not yet tested anything, I’m in the early steps of the process but it seems useful if any of you is still on the topic.

Did you get it working?

Not yet on my side, busy with other topics for the moment but still it seems a right way

I believe this is the best way to do it. It looks more simple since you can use his nsdo command. Which makes it less prone to errors when setting up. Also, he has a solution to actually reach your Transmission WebUI, even if Transmission runs in the network namespace.

and:

I remember spending quite some time on it but I am such a noob. I really need more explanation.

@trohn_javolta @shamael

I have never gotten this close. The blog from Austin Adams is the way to go, I just interpreted it wrongly.
On Debian Stretch, I have it almost completely working.

It is extremely easy to setup(!) but it involves one crazy magical script which doesn’t seem to work well on Debian Stretch. I have therefore created a topic on the OpenVPN forum, also explaining the exact steps to take.

I am sure you will be shocked how easy it is :wink: Now hoping someone can fix the script for Debian Stretch.

https://forums.openvpn.net/viewtopic.php?f=15&t=25690