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. 1 (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
Footnotes
- Note, this really isn’t the machine room network of my place of work. [↩]

