Routes for two openvpn connections (different hosts) in the same client

Im trying to make multiple tunnels in the same client, and after a successful connection to the openvpn server I've applied some routes for the tunnels created without success. My first tunnel works but the second one does not. Im doing it like this:

Routes before doing nothing

default         192.168.1.1     0.0.0.0         UG    0      0        0 enp3s0
link-local      *               255.255.0.0     U     1000   0        0 enp3s0
192.168.1.0     *               255.255.255.0   U     0      0        0 enp3s0

First tunnel

France.ovpn

client
dev tun
proto udp
remote france.privateinternetaccess.com
lport 1190
resolv-retry infinite
persist-key
persist-tun
cipher aes-128-cbc
auth sha1
tls-client
remote-cert-tls server
auth-user-pass /etc/openvpn/piaauth.txt
comp-lzo
verb 1
reneg-sec 0
crl-verify /etc/openvpn/crl.rsa.2048.pem
ca /etc/openvpn/ca.rsa.2048.crt
disable-occ
lport 1189
rport 1198

|

sudo /usr/sbin/openvpn --config /etc/openvpn/France.ovpn --dev tun0 --route-noexec


sudo route add -net 10.88.10.1 gw 10.88.10.5 netmask 255.255.255.255 dev tun0
sudo route add -net 10.88.10.5 gw * netmask 255.255.255.255 dev tun0
sudo route add -net 128.0.0.0 gw 10.88.10.5 netmask 128.0.0.0 dev tun0
sudo route add -net 172.98.67.121 gw 192.168.1.1 netmask 255.255.255.255 enp3s0

Routes after first tunnel

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.1.1     0.0.0.0         UG    0      0        0 enp3s0
10.88.10.1      10.88.10.5      255.255.255.255 UGH   0      0        0 tun0
10.88.10.5      *               255.255.255.255 UH    0      0        0 tun0
128.0.0.0       10.88.10.5      128.0.0.0       UG    0      0        0 tun0
link-local      *               255.255.0.0     U     1000   0        0 enp3s0
172.98.67.121   192.168.1.1     255.255.255.255 UGH   0      0        0 enp3s0
192.168.1.0     *               255.255.255.0   U     0      0        0 enp3s0

All works perfect

Now I try with this:

Norway.ovpn

client
dev tun
proto udp
remote no.privateinternetaccess.com
resolv-retry infinite
persist-key
persist-tun
cipher aes-128-cbc
auth sha1
tls-client
remote-cert-tls server
auth-user-pass /etc/openvpn/piaauth.txt
comp-lzo
verb 1
reneg-sec 0
crl-verify /etc/openvpn/crl.rsa.2048.pem
ca /etc/openvpn/ca.rsa.2048.crt
disable-occ
lport 1187
rport 1198

sudo /usr/sbin/openvpn --config /etc/openvpn/Norway.ovpn --route-noexec

sudo route add -net 10.39.10.1 gw 10.39.10.5 netmask 255.255.255.255 dev tun1
sudo route add -net 10.39.10.5 gw * netmask 255.255.255.255 dev tun1
sudo route add -net 108.61.123.81 gw 192.168.1.1 netmask 255.255.255.255 enp3s0

Routes now:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.1.1     0.0.0.0         UG    0      0        0 enp3s0
10.39.10.1      10.39.10.5      255.255.255.255 UGH   0      0        0 tun1
10.39.10.5      *               255.255.255.255 UH    0      0        0 tun1
10.8.10.1       10.8.10.5       255.255.255.255 UGH   0      0        0 tun0
10.8.10.5       *               255.255.255.255 UH    0      0        0 tun0
108.61.123.81.c 192.168.1.1     255.255.255.255 UGH   0      0        0 enp3s0
128.0.0.0       10.8.10.5       128.0.0.0       UG    0      0        0 tun0
link-local      *               255.255.0.0     U     1000   0        0 enp3s0
172.98.67.121   192.168.1.1     255.255.255.255 UGH   0      0        0 enp3s0
192.168.1.0     *               255.255.255.0   U     0      0        0 enp3s0

And I think that the problem comes after trying to add the last route:

sudo route add -net 128.0.0.0 gw 10.39.10.5 netmask 128.0.0.0 dev tun1

because I used 128.0.0.0 previously with tun0. I tried to change it for something different like 252.0.0.0 or 224.0.0.0 for example but it does not work. And if I try with 128.0.0.0 tun1 works but tun0 does not. What should I do in order to make both tunnels working at the same time?


Main routing table

Only 1 default route is possible per routing table. If you want to add the routes to the main routing table, then you need to decide which gateway shall be used as default route.

When redirect-gateway def1 is used, OpenVPN adds 2 (more specific) routes (each one of them matching half of the ip address range) to the main routing table which override the default route without deleting it:

0.0.0.0/1 via 10.8.0.1 dev tun0       # network 0.0.0.0    mask 128.0.0.0
default via 10.0.2.2 dev eth0         # network 0.0.0.0    mask 0.0.0.0
128.0.0.0/1 via 10.8.0.1 dev tun0     # network 128.0.0.0  mask 128.0.0.0

The same applies for these 2 override routes. It is not possible to add another route with 0.0.0.0/1 or 128.0.0.0/1 to the main routing table.

Policy based routing

I suspect what you want to do is to configure some sort of split tunneling. It can be achieved using policy based routing as follows, assuming that the tun0 and tun1 devices are used.

First add 2 more routing tables:

echo "100 tun0" >> /etc/iproute2/rt_tables
echo "101 tun1" >> /etc/iproute2/rt_tables

Create a /etc/openvpn/route-up.sh script to automatically add routes when openvpn connects:

#!/bin/bash

RULE_EXIST=$(ip rule list | grep "from ${ifconfig_local}" | wc -l)
if [ $RULE_EXIST -ne 0 ]; then
  ip rule del from "${ifconfig_local}" lookup "${dev}"
fi
ip rule add from "${ifconfig_local}" lookup "${dev}"
ip route add default via "${route_vpn_gateway}" dev "${dev}" table "${dev}"

Run chmod +x /etc/openvpn/route-up.sh

Add those lines to the OpenVPN client config files:

route-noexec
route-up /etc/openvpn/route-up.sh
script-security 2

Now connect with both clients and check the routing tables:

root@debian:/etc/openvpn# ip route show
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0  scope link  src 10.0.2.15
10.8.0.0/24 dev tun0  proto kernel  scope link  src 10.8.0.2

root@debian:/etc/openvpn# ip route show table tun0
default via 10.8.0.1 dev tun0

root@debian:/etc/openvpn# ip route show table tun1
default via 10.0.2.2 dev eth0

root@debian:/etc/openvpn# ip rule show
0:      from all lookup local
32762:  from 10.8.0.2 lookup tun0
32763:  from 10.0.2.15 lookup tun1
32766:  from all lookup main
32767:  from all lookup default

Now you need to decide what to do. For example to enable simple load balancing, add the following route:

ip route del default
ip route add default scope global nexthop via 10.8.0.1 dev tun0 weight 1 \
nexthop via 10.0.2.2 dev eth0 weight 1

After that, the main routing table looks as follows:

root@debian:/etc/openvpn# ip route show
default
        nexthop via 10.8.0.1  dev tun0 weight 1
        nexthop via 10.0.2.2  dev eth0 weight 1
10.0.2.0/24 dev eth0  scope link  src 10.0.2.15
10.8.0.0/24 dev tun0  proto kernel  scope link  src 10.8.0.2

Using policy based routing, you can do cool things. See references below for more ideas.

OpenVPN script debugging

Add this to the route-up.sh script to help debugging and see what variables are available:

log=/tmp/ovpn.log
exec >>"$log" 2>&1
chmod 666 "$log" 2>/dev/null
printenv

Then run tail -f /tmp/ovpn.log while connecting.

References

  • Marking packets with iptables for policy routing based on port
  • A Quick Introduction to Linux Policy Routing
  • Linux Advanced Routing & Traffic Control HOWTO
  • Guide to IP Layer Network Administration with Linux