Split Tunnel VPN

Install OpenVPN Community Edition

Ref.: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-debian-10

apt update
apt install openvpn

Create vpn User

adduser --disabled-login vpn

Create /dev/net/tun

Check with:

ls -lad /dev/net/tun

Result:
crw-rw-rw- 1 root root 10, 200 Jul 21 06:09 /dev/net/tun
#!/bin/bash

mkdir -p /dev/net
mknod /dev/net/tun c 10 200
chmod 600 /dev/net/tun

/etc/init.d/openvpn restart

LXC Container

lxc.mount.entry = /dev/net/tun /dev/net/tun none bind create=file

Create VPN Config

Download from NordVPN:

apt -y install unzip
wget https://downloads.nordcdn.com/configs/archives/servers/ovpn.zip
unzip ovpn.zip
cp ./ovpn_tcp/nl816.nordvpn.com.tcp.ovpn  /etc/openvpn/openvpn.conf

Add to /etc/openvpn/openvpn.conf:

auth-nocache
disable-occ
script-security 2
route-noexec

Change login cred:

sed -i -e ‘s/auth-user-pass/auth-user-pass \/etc\/openvpn\/login.txt/g' /etc/openvpn/openvpn.conf

Add up/down scrips:

#up and down scripts to be executed when VPN starts or stops
up /etc/openvpn/iptables.sh
down /etc/openvpn/update-resolv-conf

Create vpn credentials file

vi /etc/openvpn/login.txt:

yourusername
yourpassword

Create systemd Service for OpenVPN

vi /etc/systemd/system/openvpn@openvpn.service

[Unit]
# HTPC Guides - www.htpcguides.com
Description=OpenVPN connection to %i
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
After=network.target

[Service]
RuntimeDirectory=openvpn
PrivateTmp=true
KillMode=mixed
Type=forking
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/%i.conf --writepid /run/openvpn/%i.pid
PIDFile=/run/openvpn/%i.pid
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/etc/openvpn
Restart=on-failure
RestartSec=3
ProtectSystem=yes
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw

[Install]
WantedBy=multi-user.target

Create service:

systemctl enable openvpn@openvpn.service

Prevent user from accessing internet

Flush iptables:

sudo iptables -F

Add rule to block vpn user's access to Internet (except the loopback device).

iptables -A OUTPUT ! -o lo -m owner –uid-owner vpn -j DROP

Create iptables

vi /etc/openvpn/iptables.sh

Update LOCALIP and NETIF!

#! /bin/bash
# Niftiest Software – www.niftiestsoftware.com
# Modified version by HTPC Guides – www.htpcguides.com

export INTERFACE="tun0"
export VPNUSER="vpn"
export LOCALIP="10.10.2.120"
export NETIF="eth0"

# flushes all the iptables rules, if you have other rules to use then add them into the script
iptables -F -t nat
iptables -F -t mangle
iptables -F -t filter

# mark packets from $VPNUSER
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT ! --dest $LOCALIP -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT --dest $LOCALIP -p udp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT --dest $LOCALIP -p tcp --dport 53 -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT ! --src $LOCALIP -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT -j CONNMARK --save-mark

# allow responses
iptables -A INPUT -i $INTERFACE -m conntrack --ctstate ESTABLISHED -j ACCEPT

# block everything incoming on $INTERFACE to prevent accidental exposing of ports
iptables -A INPUT -i $INTERFACE -j REJECT

# let $VPNUSER access lo and $INTERFACE
iptables -A OUTPUT -o lo -m owner --uid-owner $VPNUSER -j ACCEPT
iptables -A OUTPUT -o $INTERFACE -m owner --uid-owner $VPNUSER -j ACCEPT

# all packets on $INTERFACE needs to be masqueraded
iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE

# reject connections from predator IP going over $NETIF
iptables -A OUTPUT ! --src $LOCALIP -o $NETIF -j REJECT

# Start routing script
/etc/openvpn/routing.sh

exit 0

Make executable chmod +x /etc/openvpn/iptables.sh

Create Resolv

vi /etc/openvpn/update-resolv-conf

foreign_option_1='dhcp-option DNS 209.222.18.222'
foreign_option_2='dhcp-option DNS 209.222.18.218'
foreign_option_3='dhcp-option DNS 8.8.8.8'

Create the routing script

vi /etc/openvpn/routing.sh

#! /bin/bash
# Niftiest Software – www.niftiestsoftware.com
# Modified version by HTPC Guides – www.htpcguides.com

VPNIF="tun0"
VPNUSER="vpn"
GATEWAYIP=$(ifconfig $VPNIF | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | egrep -v '255|(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' | tail -n1)
if [[ `ip rule list | grep -c 0x1` == 0 ]]; then
ip rule add from all fwmark 0x1 lookup $VPNUSER
fi
ip route replace default via $GATEWAYIP table $VPNUSER
ip route append default via 127.0.0.1 dev lo table $VPNUSER
ip route flush cache

# run update-resolv-conf script to set VPN DNS
/etc/openvpn/update-resolv-conf

exit 0

Make executable:

sudo chmod +x /etc/openvpn/routing.sh

Configure Split Tunnel VPN Routing

vi /etc/iproute2/rt_tables

Add the vpn user table at the bottom of the file

200 vpn

Change Reverse Path Filtering

vi /etc/sysctl.d/9999-vpn.conf

Update the eth0 interface!

net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2

Apply new sysctl rules:

sysctl –system

Test OpenVPN service

systemctl stop openvpn@openvpn.service
systemctl start openvpn@openvpn.service
systemctl status openvpn@openvpn.service
systemctl restart openvpn@openvpn.service

Test vpn user

sudo -u vpn -i – curl ipinfo.io