In this little tutorial i explain how to build a raspberry pi vpn router. This raspi will be equiped with an additional ethernet adapter and work as a router between your pc and your home lan or between portions of your local network. The raspi will use NAT to connect devices connected to eth1 to your ISP or a choice of multiple vpns. What was important for me is to ensure that your device only passes the selected output channel. If the vpn breaks down, no internet even if the second vpn or your isps connection still works. No auto switch to your isp.

Requirements:

  • USB Ethernet adapter
  • Linux skills
  • Rasperry pi with fresh raspbian

How does it work?

Your eth0 is connected to your local lan and gets his routing via dhcp. Your eth1 is connected to your computer. On eth1 dnsmasq serves the 192.168.111.X network of vpn routable devices.

Basically we are enable NAT routing on the raspi and by default null-route everything incoming. After this, we create a separate routing table defgw with your eth0 default gateway aquired by dhcp.

We enable NAT on every tunX for our vpns. Every VPN connection will add a separate routing table vpnX with your raspi as gateway.

Now you can decide to assign an ip out of the private pool 192.168.111.X to a routing table.

If you choose defgw it gets routed to your local network and out to your isp.

If you choose vpnX it gets routed through the specified vpn.

If a route breaks or gets removed, the null-route rule take care of it instead falling back to your default gatework (ISP).

Install software

Packages:

  • openvpn
  • dnsmasq

Routing

Add to /etc/iproute2/rt_tables:

200 vpn1
201 vpn2
152 null
153 defgw

Network setup

/etc/network/interfaces

source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
    post-up /home/pi/ifup.sh

auto eth1
iface eth1 inet static
    address 192.168.111.1
    netmask 255.255.255.0
    network 192.168.111.0
    broadcast 192.168.111.255

The up-script sets up the defgw route.

/home/pi/ifup.sh

#!/bin/bash
if [ "$IFACE" != "eth0" ]; then
    echo "No suitable interface"
    exit 0
fi

gw=$(ip route show dev eth0 | grep default | head -n 1 | awk '{print $3}')
if [ -z "$gw" ]; then
    echo "No default gateway found"
    exit 0
fi

ip route add default via $gw dev eth0 table defgw

exit 0

Startup

/etc/rc.local

echo "Enable null routing"
ip route add default via 127.0.0.1 dev lo table null
ip rule add from 192.168.111.0/24 table null
ip rule add from 192.168.111.1

echo "Enable NAT on eth0"
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE


# NAT on tunX
echo "Enable NAT on tunX"
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o tun1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o tun2 -j MASQUERADE
iptables -t nat -A POSTROUTING -o tun3 -j MASQUERADE

echo "Starting vpn service 1"
start-stop-daemon --start --background --make-pidfile --oknodo --user root --name vpn1 --pidfile /var/run/vpn1.pid --startas /home/pi/vpn1.sh --chuid root 
echo "Starting vpn service 2"
start-stop-daemon --start --background --make-pidfile --oknodo --user root --name vpn2 --pidfile /var/run/vpn2.pid --startas /home/pi/vpn2.sh --chuid root

exit 0

VPN

/home/pi/vpnX.sh

#!/bin/bash
openvpn --cd /home/pi/.openvpn --config yourconfig.ovpn --up up.sh --script-security 2 --route-nopull

You need a seperate up script for every openvpn connection, change the routing table vpn1 to your need.

So your vpns are clearly distinguished by routing table and not device.

/home/pi/.openvpn/up.sh:

#!/bin/sh
ip route add default via $ifconfig_local dev $dev table vpn1

Switch the routing table

For demonstration purpose i use a connected device with ip 192.168.111.33:

Switch to vpn1:

ip rule add from 192.168.111.33 table vpn1
Remove afterwards:
ip rule del from 192.168.111.33 table vpn1

Switch to vpn2:

ip rule add from 192.168.111.33 table vpn2
Remove afterwards:
ip rule del from 192.168.111.33 table vpn2

Switch to your isp route:

ip rule add from 192.168.111.33 table defgw
Remove afterwards:
ip rule del from 192.168.111.33 table defgw