0%

Run a Script After OpenVPN Connects

I was using OpenVPN on a cloud server to connect back into the company network, and after the tunnel came up, some of my original routes stopped working.

After checking the routing table, I found that the VPN was pushing too many routes and overriding addresses that I still needed to reach through the original network path. The practical fix was to run a custom script after the VPN connected and then replace or add the routes I wanted.

Looking at the openvpn man page, there are two options that matter here.

up: run a command after the VPN connection is established:

1
2
3
4
5
6
7
8
--up cmd
Run command cmd after successful TUN/TAP device open (pre --user UID change).

cmd consists of a path to script (or executable program), optionally followed by arguments. The path and arguments may be single- or
double-quoted and/or escaped using a backslash, and should be separated by one or more spaces.

The up command is useful for specifying route commands which route IP traffic destined for private subnets which exist at the other end
of the VPN connection into the tunnel.

script-security: set this to 2 to allow user-defined scripts:

1
2
3
4
5
6
7
8
--script-security level
This directive offers policy-level control over OpenVPN's usage of external programs and scripts. Lower level values are more restric-
tive, higher values are more permissive. Settings for level:

0 -- Strictly no calling of external programs.
1 -- (Default) Only call built-in executables such as ifconfig, ip, route, or netsh.
2 -- Allow calling of built-in executables and user-defined scripts.
3 -- Allow passwords to be passed to scripts via environmental variables (potentially unsafe).

So I created a script named post_action.sh under /etc/openvpn/ and used it to replace the route after the VPN came up:

1
2
3
#!/bin/sh

ip route replace 172.16.2.0/24 via 192.168.139.1 dev eth0

Make it executable:

1
chmod +x /etc/openvpn/post_action.sh

Then add these settings to the VPN configuration file, or pass them on the command line:

1
2
script-security 2
up /etc/openvpn/post_action.sh

After restarting OpenVPN, the routing behavior was back to normal.

Update on July 19, 2021:

If you need the command to run after all pushed routes have been applied, use route-up instead:

1
2
script-security 2
route-up /etc/openvpn/post_action.sh

While I am at it, here is a sample systemd service file for OpenVPN that is handy to keep around:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# /lib/systemd/system/vpn_knktc.service
[Unit]
Description=OpenVPN tunnel for test
After=syslog.target network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO

[Service]
PrivateTmp=true
WorkingDirectory=/etc/openvpn/
ExecStart=/usr/sbin/openvpn --config knktc.ovpn
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
KillMode=process

[Install]
WantedBy=multi-user.target
如果我的文字帮到了您,那么可不可以请我喝罐可乐?