Routing a particular subnet into a VPN tunnel
This can be achieved using a custom routing table and policy (I recently did something very similar myself)
Firstly create a custom routing table for your VPN
echo "10 vpn" >> /etc/iproute2/rt_tables
Tell iproute2 to use this routing table for traffic to and from your 192.168.2.0 network
ip rule add from 192.168.2.0/24 table vpn ip rule add to 192.168.2.0/24 table vpn
Set up NAT masquerading for the 192.168.2.0 network
iptables -A FORWARD -i eth0:2 -s 192.168.2.0/24 -j ACCEPT iptables -A FORWARD -i tun0 -d 192.168.2.0/24 -j ACCEPT iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o tun0 -j MASQUERADE
Enable IP forwarding if it's not enabled (required for NAT)
echo 1 > /proc/sys/net/ipv4/ip_forward
In your OpenVPN config add the following lines
#Prevents default gateway from being set on the default routing table route-noexec #Allows route-up script to be executed script-security 2 #Calls custom shell script after connection to add necessary routes route-up /etc/openvpn/route-up.sh
Create a custom shell script in /etc/openvpn/route-up.sh and chmod +x it
#!/bin/sh #Clear all routes on vpn routing table (this is to make sure there isn't any crap left over from a previous vpn connection /sbin/ip route flush table vpn #Copy routing table from main routing table into vpn table /sbin/ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table vpn $ROUTE; done #Add default gateway to vpn routing table /sbin/ip route add default via ${route_vpn_gateway} dev ${dev} table vpn
Steps 2 and 3 will not persist across reboots so you will need to add those parts to your init scripts as required.
Related videos on Youtube
moonmoon
Updated on September 18, 2022Comments
-
moonmoon over 1 year
My network looks like this:
I'm trying configure my router so that the subnet (192.168.2.0/24) is routed over the VPN tunnel (tun0) on the gateway/router.
While at the same time clients on the subnet (192.168.1.0/24) are routed directly out over ppp0, ie not through the VPN.
I don't want to run VPN software clients, and certain clients on the network need direct access. eg a windows gaming computer, voip phone etc.
My router also runs an unbound DNS server that forwards DNS lookups to dnscrypt-proxy.
The network interfaces on the router are configured like:
auto lo iface lo inet loopback auto lo:1 iface lo:1 inet static address 127.0.0.2 netmask 255.0.0.0 auto eth0 iface eth0 inet static address 192.168.1.1 netmask 255.255.255.0 # Virtual interface auto eth0:2 iface eth0:2 inet static address 192.168.2.1 netmask 255.255.255.0 auto eth1 iface eth1 inet static address 192.168.0.2 netmask 255.255.255.252 auto ppp0 iface ppp0 inet ppp pre-up ip link set dev eth1 up provider <isp> post-down ip link set dev eth1 down
For the moment I'm using a virtual interface ie eth0:2. I am also wondering if this is appropriate or should that be a VLAN ie eth0.2?
As far as I was aware the only difference would be that clients would then require a VLAN interface eg:
/etc/systemd/network/MyEth.network
[Match] Name=enp10s0 [Network] DHCP=v4 DNS=192.168.2.1 Address=192.168.2.30/24 Gateway=192.168.2.1 VLAN=vlan2
/etc/systemd/network/MyEth.netdev
[NetDev] Name=vlan2 Kind=vlan [VLAN] Id=2
and be unable to cross over subnets eg 192.168.1.10 would be unable to talk to 192.168.2.10.
The iptables rules I've attempted to get this working with are as follows:
iptables -F iptables -t nat -F export WAN=ppp0 # Link to ISP export INT_IF=eth0 # Interface that serves internal network export EXT_IF=eth1 # Interface between router and modem export WAN_TUNNEL=tun0 # VPN tunnel created by OpenVPN export VPN_VLAN_IF=eth0:2 # Interface internal clients have as their gateway # Allows internet access on gateway iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m conntrack --ctstate INVALID -j DROP ############# # NAT Rules # ############################################################################### # VPN iptables -I FORWARD -i ${VPN_VLAN_IF} -d 192.168.2.0/24 -j DROP iptables -A FORWARD -i ${VPN_VLAN_IF} -s 192.168.2.0/24 -j ACCEPT iptables -A FORWARD -i ${WAN_TUNNEL} -d 192.168.2.0/24 -j ACCEPT iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o ${WAN_TUNNEL} -j MASQUERADE ############################################################################### ############################################################################### # NO VPN iptables -I FORWARD -i ${INT_IF} -d 192.168.1.0/24 -j DROP iptables -A FORWARD -i ${INT_IF} -s 192.168.1.0/24 -j ACCEPT iptables -A FORWARD -i ${WAN} -d 192.168.1.0/24 -j ACCEPT iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ${WAN} -j MASQUERADE ############################################################################### iptables -P INPUT DROP iptables -P OUTPUT ACCEPT iptables -P FORWARD DROP echo 1 > /proc/sys/net/ipv4/ip_forward for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done /etc/init.d/iptables save
I also expect that I would need to use route-nopull in my openvpn configuration, otherwise everything on the gateway would be routed over the VPN?
By default when I connect to the OpenVPN server I see:
openvpn[3469]: /sbin/ip route add <ip_of_vpn> dev ppp0 openvpn[3469]: /sbin/ip route add 0.0.0.0/1 via 172.16.32.1 openvpn[3469]: /sbin/ip route add 128.0.0.0/1 via 172.16.32.1
which results in a route like:
ip route 0.0.0.0/1 via 172.16.32.1 dev tun0 default dev ppp0 scope link metric 300 <ip_of_vpn> dev ppp0 scope link 128.0.0.0/1 via 172.16.32.1 dev tun0 172.16.32.0/20 dev tun0 proto kernel scope link src 172.16.39.64 192.168.0.0/30 dev eth1 proto kernel scope link src 192.168.0.2 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.1 192.168.2.0/24 dev eth0 proto kernel scope link src 192.168.2.1 <ip_from_isp> dev ppp0 proto kernel scope link src X.X.X.X
Would I need a static route to route 192.168.2.0/24 to the VPN ie to tun0
-
y_nk over 7 yearstried with openwrt and a mwan setup, didn't work. i suspect mwan rules to mess up with this