Hardening OpenVPN Security
One of the often-repeated maxims of network security is that one should never place so much trust in a single security component that its failure causes a catastrophic security breach. OpenVPN provides several mechanisms to add additional security layers to hedge against such an outcome.
The tls-auth directive adds an additional HMAC signature to all SSL/TLS handshake packets for integrity verification. Any UDP packet not bearing the correct HMAC signature can be dropped without further processing. The tls-auth HMAC signature provides an additional level of security above and beyond that provided by SSL/TLS. It can protect against:
- DoS attacks or port flooding on the OpenVPN UDP port.
- Port scanning to determine which server UDP ports are in a listening state.
- Buffer overflow vulnerabilities in the SSL/TLS implementation.
- SSL/TLS handshake initiations from unauthorized machines (while such handshakes would ultimately fail to authenticate, tls-auth can cut them off at a much earlier point).
Using tls-auth requires that you generate a shared-secret key that is used in addition to the standard RSA certificate/key:
openvpn --genkey --secret ta.key
This command will generate an OpenVPN static key and write it to the file ta.key. This key should be copied over a pre-existing secure channel to the server and all client machines. It can be placed in the same directory as the RSA .key and .crt files.
In the server configuration, add:
tls-auth ta.key 0
In the client configuration, add:
tls-auth ta.key 1
While OpenVPN allows either the TCP or UDP protocol to be used as the VPN carrier connection, the UDP protocol will provide better protection against DoS attacks and port scanning than TCP:
user/group (non-Windows only)
OpenVPN has been very carefully designed to allow root privileges to be dropped after initialization, and this feature should always be used on Linux/BSD/Solaris. Without root privileges, a running OpenVPN server daemon provides a far less enticing target to an attacker.
user nobody group nobody
Unprivileged mode (Linux only)
On Linux OpenVPN can be run completely unprivileged. This configuration is a little more complex, but provides best security.
In order to work with this configuration, OpenVPN must be configured to use iproute interface, this is done by specifying --enable-iproute2 to configure script. sudo package should also be available on your system.
This configuration uses the Linux ability to change the permission of a tun device, so that unprivileged user may access it. It also uses sudo in order to execute iproute so that interface properties and routing table may be modified.
- Write the following script and place it at: /usr/local/sbin/unpriv-ip:
#!/bin/sh sudo /sbin/ip $*
- Execute visudo, and add the followings to allow user 'user1' to execute /sbin/ip:
user1 ALL=(ALL) NOPASSWD: /sbin/ip
- You can also enable a group of users with the following command:
%users ALL=(ALL) NOPASSWD: /sbin/ip
- Add the following to your OpenVPN configuration:
dev tunX/tapX iproute /usr/local/sbin/unpriv-ip
- Please note that you must select constant X and specify tun or tap not both.
- As root add persistant interface, and permit user and/or group to manage it, the following create tunX (replace with your own) and allow user1 and group users to access it.
openvpn --mktun --dev tunX --type tun --user user1 --group users
- Run OpenVPN in the context of the unprivileged user.
Further security constraints may be added by examining the parameters at the /usr/local/sbin/unpriv-ip script.
chroot (non-Windows only)
The chroot directive allows you to lock the OpenVPN daemon into a so-called chroot jail, where the daemon would not be able to access any part of the host system's filesystem except for the specific directory given as a parameter to the directive. For example,
would cause the OpenVPN daemon to cd into the jail subdirectory on initialization, and would then reorient its root filesystem to this directory so that it would be impossible thereafter for the daemon to access any files outside of jail and its subdirectory tree. This is important from a security perspective, because even if an attacker were able to compromise the server with a code insertion exploit, the exploit would be locked out of most of the server's filesystem.
Caveats: because chroot reorients the filesystem (from the perspective of the daemon only), it is necessary to place any files which OpenVPN might need after initialization in the jail directory, such as:
- the crl-verify file, or
- the client-config-dir directory.
Larger RSA keys
The RSA key size is controlled by the KEY_SIZE variable in the easy-rsa/vars file, which must be set before any keys are generated. Currently set to 1024 by default, this value can reasonably be increased to 2048 with no negative impact on VPN tunnel performance, except for a slightly slower SSL/TLS renegotiation handshake which occurs once per client per hour, and a much slower one-time Diffie Hellman parameters generation process using the easy-rsa/build-dh script.
Larger symmetric keys
By default OpenVPN uses Blowfish, a 128 bit symmetrical cipher.
OpenVPN automatically supports any cipher which is supported by the OpenSSL library, and as such can support ciphers which use large key sizes. For example, the 256-bit version of AES (Advanced Encryption Standard) can be used by adding the following to both server and client configuration files:
Keep the root key (ca.key) on a standalone machine without a network connection
One of the security benefits of using an X509 PKI (as OpenVPN does) is that the root CA key (ca.key) need not be present on the OpenVPN server machine. In a high security environment, you might want to specially designate a machine for key signing purposes, keep the machine well-protected physically, and disconnect it from all networks. Floppy disks can be used to move key files back and forth, as necessary. Such measures make it extremely difficult for an attacker to steal the root key, short of physical theft of the key signing machine.