Thursday, August 29, 2019

Getting Split-Tunneling in Linux to work

In general when you are connected to virtual private network of your office without split tunneling, all the data will go through your vpn network interface.
  1. It makes your system network to work slow as all the data will go through the vpn network.
  2. There might be some domains, websites which might be restricted on vpn network. For eg torrent application is running which might be prohibited in your office network.
The purpose of this article is to allow normal internet traffic via systems default network interface (eth0) and private network traffic via vpn interface (vpn0).

Next >>

The first thing to make sure is that once vpn is connected that it should not be your default route gateway.
This is achieved using vpn profile in Network Manager. Go through the vpn profile in Network Manager settings and check the box as shown below.

Next >>

The route table should look like this. Note the default traffic is still going through eth0 as per the table.

$ route -n
Kernel IP routing table
Destination  Gateway     Genmask Flags Metric Ref Use Iface UG 600 0 0 eth0 U 50 0 0 vpn0 U 1000 0 0 eth0 U 600 0 0 eth0 UH 600 0 0 eth0 UGH 600 0 0 eth0 is the default route, any route which is not matching will end up in this route and go through it.
There may be some extra routes added by the vpn client, so you can keep them. Some VPN servers push the routes from the VPN server so as to make sure the particular range of IP traffic always go through the particular route.
  1. is the endpoint IP through which the vpn traffic flows in and out. This is an internally assigned IP by vpn server. Each and every vpn client will get a different IP.
  2. is the public IP through which the vpn traffic flows via internet. This IP will be common throughout all vpn clients and usually this is the vpn public server IP.

Next >>

Integrate custom script into the system default behavior whenever a vpn client connection is established and terminated.
Let’s assume you have created a vpnscript.

# Don't run until we bring up a real network device
[ "$IFACE" != "lo" ] || exit 0
if [ "$IFACE" = "vpn0" ]; then
if [ "$MODE" = "start" ] && [ "$ADDRFAM" = "inet" ]; then
if [ "$MODE" = "stop" ] && [ "$ADDRFAM" = "inet" ]; then
#do something else
Make the vpnscript functional. You can also copy these scripts to a permanent place. Change $HOME to an absolute path..

sudo ln -vsf $HOME/bin/vpnscript /etc/network/if-up.d/
sudo ln -vsf $HOME/bin/vpnscript /etc/network/if-down.d/
sudo ln -vsf $HOME/bin/vpnscript /etc/network/if-post-down.d/

route add dev vpn0
route add dev vpn0
route add VPN.SYSTEM.IP.0 dev vpn0
route add dns.vpn.ip dev vpn0

dns.vpn.ip could be your vpn dns server, this would also be populated into /etc/resolv.conf once vpn is connected. You can also use two dns servers in this order to make sure if the dns lookup fails in the public server then the VPN dns server is tried for lookup.
  Public/Default DNS server
  VPN DNS server

Manually enter the hosts entries which are contacted frequently. This may not be required if you are only using DNS server approach.


Woof!! That is a lot of networking system but not too much for a networking expert.
Now take a pause and lets understand before moving forward.

Scenario 1:
You want to surf
The public dns server will resolve your dns query to a public IP and the internet traffic goes via eth0

Scenario 2:
You want to do ssh to
The dns query to will fail first via public IP then the system will try to resolve dns query using vpn dns server which will eventually resolve to an IP.
Hint: Try this command first to make sure the dns query is working properly for a vpn domain.

$ dig
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11024
;; flags: qr rd ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
; IN A
;; Query time: 0 msec
;; WHEN: Thu Aug 29 20:48:41 IST 2019
;; MSG SIZE rcvd: 78

After the IP is resolved to, the system will check if there a specific route in the routing table. If it is there then it will go through that interface, otherwise the ssh will try to connect it through default route which is eth0.
If it fails then you have to add the route manually like this.

$ sudo route add dev vpn0
#also add it in for future use.

Next >>

Seamless browsing in Firefox/Chrome without worrying about the data traffic. This will also work if your VPN provider has http proxy. In my case I will use socks5 proxy.
  • Install the FoxyProxy Extension/Add-on
  • Select the default mode User proxies based on their pre-defined patterns and priorities.
  • Add a proxy for your vpn provider and enter details.
  • Add the pattern rules for this proxy, for eg: **
  • If there is an option to use proxy for dns then select this option to make sure private domains are resolved via this proxy.
  • Great enjoy!!
Socks5 proxy using ssh
$ ssh -D 5353 -o ConnectTimeout=10 -o ConnectionAttempts=1 -C -N
# -D dynamic socks5 port
# -C compression
# -o for extra option
# -N do not execute any remote command