Split Routing with OpenVPN
My place of work has installed a VPN that moderates our access to the server network using the OpenVPN protocol. This is a good thing, but in its default configuration it would send all traffic -- even that not destined for the machine room network -- through the VPN. Since most of what I do doesn't involve servers in the machine room, I wanted to change the configuration of the OpenVPN client to only send the machine room traffic through the VPN and everything else through the (original) default gateway. As it turns out, this involves tweaking the routing tables.
In its default configuration, the OpenVPN client establishes a default route pointing to the OpenVPN server as the gateway. What I needed to do is remove that default route to the OpenVPN server gateway, recreate the original default route to the underlying interface's gateway, and add a new specific route for the machine room network using the OpenVPN server gateway. These additions to the "ovpn" file were:
route-delay 2
route-up "/some/location/openvpn-default-route-reset.sh"
route 193.20.135.0/24 255.255.255.0 vpn_gateway
The "route-delay" line forces the two subsequent changes to happen after all of the OpenVPN-driven routing changes are made. The "route-up" line runs a shell script that deletes the OpenVPN-supplied default route and adds the one pointing back to the underlying interface's gateway. (More on this shell script below.) The "route" line adds the machine room specific network through the OpenVPN tunnel. ((Note, this really isn't the machine room network of my place of work.)) (The "vpn_gateway" is a keyword in the configuration file that is replaced by the gateway address of the OpenVPN tunnel at runtime.)
For reasons I don't understand, I couldn't delete and re-add the default route via the OpenVPN configuration file. Instead, I needed to create an external shell script with those commands and execute that script via the "route-up" configuration line. The contents of the shell script are really simple:
#!/bin/bash
/sbin/route delete default
/sbin/route add default $route_net_gateway
OpenVPN will push a bunch of environment variables in to the subprocess, and one of them is $route_net_gateway
that gets the "pre-existing default IP gateway in the system routing table." That value is used in the third line to reset the default gateway. This script gets run as root, so perform due diligence to protect the script (
With that in place, my network routing tables look something like this:
Internet:
Destination Gateway Flags Refs Use Netif Expire
default 192.168.2.1 UGSc 40 0 en1
10.242.2.1/32 10.242.2.9 UGSc 0 0 tun0
10.242.2.9 10.242.2.10 UH 4 1 tun0
127 127.0.0.1 UCS 0 0 lo0
127.0.0.1 127.0.0.1 UH 12 15704029 lo0
192.168.2 link#5 UCS 2 0 en1
192.168.2.1 0:c0:49:ff:8c:c5 UHLWI 42 108 en1 1158
192.168.2.3 127.0.0.1 UHS 0 9 lo0
193.20.135 10.242.2.9 UGSc 2 0 tun0
193.20.135.2/32 192.168.2.1 UGSc 1 0 en1