Prerequistes and Installation

I am running OpenVPN on OpenBSD 6.0. I won't cover the installation details here which are well described in this post called "Setting up OpenVPN on OpenBSD". Keep in mind you'll need two packages to install, 'openvpn' and 'easy-rsa'. The latter will pull in OpenSSL, but don't worry, OpenVPN is linked against LibreSSL from OpenBSD base - which, by the way, is yet another reason while I prefer OpenBSD over other systems:

$ ldd /usr/local/sbin/openvpn

       Start            End              Type Open Ref GrpRef Name
       0000015eeff00000 0000015ef03a1000 exe  1    0   0      /usr/local/sbin/openvpn
       00000161c26da000 00000161c2af9000 rlib 0    1   0      /usr/local/lib/
       0000016145aab000 0000016145f05000 rlib 0    1   0      /usr/lib/
       000001616dda6000 000001616e377000 rlib 0    2   0      /usr/lib/
       00000160f5840000 00000160f5d09000 rlib 0    1   0      /usr/lib/
       0000016191e00000 0000016191e00000 rtld 0    1   0      /usr/libexec/

EKU vs. nsCertType

Once you have installed OpenVPN and Easy-RSA you need to set up your CA and related keys. Again, the aforementioned blog post does a good job in explaining the details. Make sure you really use Easy-RSA for setting this all up. Version 3, the one that is available as OpenBSD package, takes care of all the gory details, including Extended Key Usage. Those supersede the non-standard ns* extensions (NSCertType) which should no longer be used. Instead, modern certificates leverage Extended Key Attributes to specify what they can be used for (TLS Web Server Authentication vs. TLS Web Client Authentication). This enables one to use the following line in the OpenVPN client config. For more background information consult this post:

remote-cert-tls server


OpenVPN has three modes of operation with respect to network topology. If you happen to not run any Windows-based system you are better off to use the modern 'subnet' scheme instead of the old 'net30' which is still the default. All three available topologies are explained in the OpenVPN wiki:

dev tun0
topology subnet

OpenVPN Hardening

There are a couple of good hardening posts out there but it's not always easy to separate the wheat from the chaff, especially when you are not a crypto guy. That said, the following configuration might not be the best at all. If you spot a mistake, drop me a comment, please. Also, make sure you did your home work: Proper permissions for certs and keys, securing your CA, choose an appropriate key size et. al.

OpenVPN uses two channels, one for control and one for data. Both accept configuration settings and different ciphers. A good intro can be found in the OpenVPN wiki.


OpenVPN authenticates packets with HMAC using SHA-1 as default message digest algorithm. My OpenVPN clients range from Mac OS X to Android and I have realized my Mac is not able to connect to the server unless the default SHA-1 HMAC is used. You may be able to strengthen this to SHA256 in your environment.

auth SHA1


The data channel encrypts packets with BF-CBC by default, (Blowfish in Cipher Block Chaining mode) and a variable key size of 128bit. You may switch to a more modern and widely adopted cipher:

cipher AES-256-CBC


The OpenVPN TLS settings steer the control channel security. Two things come to mind: Enforce a minimum TLS version to skip the old and broken ones and choose a secure and fast cipher:

tls-version-min 1.2

Out of various ciphers available, these seem to be the ones that balance security and interoperability. Although this may hold true for Android and Mac OS X only (haven't connected my girlfriend's iPhone yet...). The OpenVPN Hardening page mentions: "Today, OpenVPN does not support TLS-ECDHE-* or more exotic cipher-suites as there is no elliptic curve support currently."


Usually, you'd probably allow all encrypted traffic ingressing the tun0 interface, by using a 'set skip tun0' line in your 'pf.conf'. However, since the tun interfaces are teared down and recreated by OpenVPN whenever the daemon needs a restart, pf will not skip the device but block all traffic. Either you reload your firewall rules on every OpenVPN restart or you specify an early pass of all tun traffic in your config (a third option is to have tun created by hostname.tun0 and start OpenVPN from there - which I dislike):

pass in quick on tun0

Starting the Daemon

Too many command line arguments are ugly. I like one can specify almost all OpenVPN options in the config file. If you even add 'daemon' there, too, the only argument the daemon needs to be given to for launching is the location of your configuration file:

/usr/local/sbin/openvpn /etc/openvpn/server.conf

Embedded Key Configuration

All keys a client requires can be provided within the client's configuration file. That way, a user doesn't have to manage multiple files that should not get renamed or moved around on his computer. If you use embedded keys, make sure to specifiy your 'key-direction' in your config file, too. The syntax is easy, a skeleton looks like this:

key-direction 1




-----BEGIN OpenVPN Static key V1-----
-----END OpenVPN Static key V1-----

Viscosity, Tunnelblick and friends

OpenVPN historically uses OpenSSL, the root cause of many crypto issues. Modern operating systems like OpenBSD have chosen to replace it with a more secure, readable and maintained successor called LibreSSL in 2014. If you choose an OpenVPN client, you are left with the same choices, specific to your platform.

For example, Viscosity has no plans to link there OpenVPN client against LibreSSL. However, Tunnelblick has just included that change in their latest beta 3.6.9beta01. Apple has already replaced OpenSSL with LibreSSL, so it's a pitty the graphical Mac clients statically link their own crypto libraries. Android is moving towards BoringSSL in version 6. Oh, and by the way, there are even pre-build OpenVPN/LibreSSL binaries for Windows :)