Sven and the Art of Computer Maintenance

Sven and the Art of Computer Maintenance

23 Feb 2019

OpenVPN configuration stacking

Recently I had to work around some network filtering systems. One of the tools I use is OpenVPN. What makes OpenVPN great is its flexibility. Either host the server yourself or use one from a third-party VPN provider, of which most support OpenVPN.

An issue with having many (third-party) OpenVPN configuration files is that they are not personalized. Sometimes you really need to add some additional options to increase security, but editing many files to allow easy switching of VPN end-points is never fun.

There is a solution for this: ‘stacked’ VPN configurations. One OpenVPN instance can load its configuration from multiple configuration files.

Imagine having a generic (minimal) OpenVPN client configuration file called client-XX-vpnprovider.ovpn:

client
dev tun

proto tcp
remote XX.vpnprovider.example 443

ca keys/ca.crt
cert keys/client.crt
key keys/client.key

Where XX is the two-letter country code of the VPN server.

There might be some provider specific options added (such as options to verify server certificate parameters, limiting ciphers, etc.), but let’s leave those out for the sake of this example.

What you’ll notice is that this is a very generic configuration, designed to work on many platforms (Linux, Windows…). Sometimes a bit of network magic is needed to make VPN’s more secure, such as when DNS servers cannot be trusted. For Arch Linux a package is available that dynamically updates a client’s DNS settings as soon as a VPN connection is started or ended. When the VPN is up, a script ensures that all DNS traffic is routed through the VPN, which prevents internet service providers from learning what the client visits through the VPN and from providing dirty (incorrect) DNS answers. When the VPN is down, the same script restores the original DNS settings.

The script has to be added to the OpenVPN configuration. Rather than editing client-XX-vpnprovider.ovpn, create a new OpenVPN configuration file with the name config-dns.ovpn:

script-security 2
up /etc/openvpn/scripts/update-systemd-resolved
down /etc/openvpn/scripts/update-systemd-resolved

Now start the OpenVPN connection with:

openvpn --config client-XX-vpnprovider.ovpn --config config-dns.ovpn

OpenVPN will load the second configuration file as if its contents were added at the end of the first. This makes it easier to switch VPN configuration options when using different configuration files.

Another way to use this is by creating another OpenVPN configuration file, start.ovpn:

config client-XX-vpnprovider.ovpn
config config-dns.ovpn

Running openvpn start.ovpn will start OpenVPN using a configuration from all referred (included) files. Note that if two or more configuration files are provided on the command line that each file must be preceded with --config.