Selectively route specific IP addresses through VPN tunnel
This is a method for setting up an OpenVPN tunnel on a Raspberry Pi router device, which does not route all traffic via the VPN, but selective IP address within the LAN.
Note 1: also uses the amazing sqm-scripts for traffic shaping, to reduce bufferbloat as much as possible.
Note 2: eth0 is our internal LAN, wlan0 is our external WAN
- Allow packet forwarding (on reboot)
$ sudo nano /etc/sysctl.conf
, uncomment this line:
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
- Load a very permissive forwarding setup
$ sudo nano /etc/iptables_rules_ipv4
, add:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o wlan0 -j ACCEPT
-A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o tun0 -j ACCEPT
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o wlan0 -j MASQUERADE
-A POSTROUTING -o tun0 -j MASQUERADE
COMMIT
- Load the ifb (intermediate functional block) interface for SQM:
$ sudo nano /etc/modules-load.d/modules.conf
- add
ifb numifbs=0
to the end
- Start SQM on boot, and load iptables rules:
$ sudo nano /etc/rc.local
, add this (before theexit 0
):
/usr/sbin/iptables-restore < /etc/iptables_rules_ipv4
/usr/bin/sqm start wlan0 # WAN gateway
- Modify your (working!) OpenVPN config to not set up a default route for all traffic:
$ sudo nano /etc/openvpn/pia.conf
, add within the existing config:
route-nopull
up '/etc/openvpn/up.sh'
route-pre-down '/etc/openvpn/route-pre-down.sh'
- Add a VPN "up" script
$ sudo touch /etc/openvpn/up.sh
$ sudo chmod 700 /etc/openvpn/up.sh
$ sudo nano /etc/openvpn/up.sh
, add:
#!/bin/bash
VPN_DEVICE=$1
VPN_GATEWAY=$4
TABLE="vpn" # defined in /etc/iproute2/rt_tables
echo "OpenVPN -> up.sh"
/usr/bin/sqm start $VPN_DEVICE
ip route flush table $TABLE
ip route add default dev $VPN_DEVICE via $VPN_GATEWAY table $TABLE
# static IP addresses to use the VPN
ip rule add from 192.168.0.2/32 table $TABLE
- Add a VPN "down" script
$ sudo touch /etc/openvpn/route-pre-down.sh
$ sudo chmod 700 /etc/openvpn/route-pre-down.sh
$ sudo nano /etc/openvpn/route-pre-down.sh
, add:
#!/bin/bash
VPN_DEVICE=$1
VPN_GATEWAY=$4
TABLE="vpn"
echo "OpenVPN -> route-pre-down.sh"
/usr/bin/sqm stop $VPN_DEVICE
ip rule flush table $TABLE
- Define the VPN routing table:
$ sudo nano /etc/iproute2/rt_tables
, add:
1 vpn
- Configure your /etc/sqm/.iface.conf scripts, see sqm-scripts for details...