OpenVPN - Getting started How-To
Setting up a VPN based on OpenVPN involves configuring several groups of options. Each group handles different elements of a VPN tunnel: the connection between server and clients, the encryption layer, the authentication layer, and finally the network configuration within the tunnel.
A helpful detail about OpenVPN configuration is that almost all options can be used either directly on the command line or through a configuration file. The primary distinction is that on the command line, you must use two leading dashes (--) for OpenVPN to recognize the options. However, when using these options in a configuration file, no leading dashes should be included.
When launching OpenVPN, you can specify which configuration file to use with the --config option. Alternatively, if no options are provided, you can directly input the file name.
# openvpn --config myvpn.conf # openvpn myvpn.conf
Note that you can use --config multiple times to merge several configuration files, or use 'config' inside a configuration file to include another configuration file.
Setting up the connection
First, you need to decide whether to use UDP or TCP for connections. Generally, UDP is preferred in most scenarios. If UDP fails to provide a reliable connection, consider using TCP. Reasons to avoid TCP can be found here.
For UDP, simply add the following to both client and server configurations:
proto udp
For TCP, the server configuration should include:
proto tcp-server
And the client configuration should specify:
proto tcp-client
Next, choose a port number. The official OpenVPN port number is 1194, but any port between 1 and 65535 is valid. If no port is specified, 1194 is used by default. Here is an example using port 443:
port 443
In the client configuration, specify the server to connect to using either hostnames or IP addresses:
remote myvpn.example.com remote 192.168.200.200
You can list multiple --remote options in the configuration file, and OpenVPN will try all of them until it gets a connection.
You can also set different port numbers and protocols for each --remote, like this:
remote myvpn.example.com 1194 udp remote myvpn.example.com 443 tcp-client
For advanced setups, it is also possible to use <connection> blocks, read more about that in the OpenVPN man page.
If you want to run multiple VPN clients on the same host, it is advisable to also add 'nobind' to your configuration file. This makes OpenVPN use a random client side port when connecting. Without it, it will use the same port number as used to connect to the server.
On the server side, you can use --local to tell OpenVPN to listen on a particular IP address. For example listening to IP address 192.168.100.1, you need first to have a network adapter configured with this IP address. Then you can add this line to the server configuration:
local 192.168.100.1
Please do note that the OpenVPN server cannot listen to multiple incoming ports, neither multiple protocols. You need separate OpenVPN instances for tackling that.
It is also possible to connect using IPv6. In the current 2.3 releases, you will need to replace udp, tcp-client or tcp-server with udp6, tcp6-client or tcp6-server as the argument to the --proto option. From the OpenVPN 2.4, OpenVPN will try both IPv6 and IPv4 when just using udp/tcp-client/tcp-server. To enforce only IPv4-only, you need to use udp4, tcp4-client or tcp4-server; and similar to enforce IPv6-only with udp6/tcp6-client or tcp6-server.
Configuring encryption
OpenVPN can work in two different modes in regards to encryption. It can use static encryption or Public Key Infrastructure (PKI). In this How-To we will cover PKI encryption, as that is the most common way to use OpenVPN.
The advantage of static encryption is that it is very easy to configure. The disadvantage of this type setup is that if your encryption key is compromised, all VPN data can easily be decrypted - even VPN data which has been captured in the past. It does not provide any type of perfect forward secrecy. And you need to ensure that the key is securely copied to both hosts. If you want to change the key, it must be changed on all clients. Last of all, static encryption also only allows a single connection to your server. How to configure static encryption can be found in the Static Key Mini Howto.
The PKI mode resolves many of these issues static encryption has. It allows multiple clients to connect to the same server, each client and server have separate keys. But it is more complex to set up. A PKI setup requires a Certificate Authority (CA). There exists plenty of alternatives for CA management. You should NOT go anywhere to buy yourself new certificates as that will make the VPN tunnel much less secure (unless you add extra authentication layers). In addition to that, a commercial certificate for OpenVPN does not provide you with any additional benefits. You will need to control your own CA for optimal security.
Setting up a proper CA is not covered in this How-To. But a good starting point will be to look at easy-rsa, in particular version 3. Easy-RSA Readme
BEWARE: One common mistake when setting up a new CA is to place all the CA files on the OpenVPN server. DO NOT DO THAT! A CA requires a private key which is used for signing the certificates your clients and servers will use. If you lose control of your CA private key, you can no longer trust any certificates from this CA. Anyone with access to this CA private key can sign new certificates without your knowledge, which then can connect to your OpenVPN server without needing to modify anything on the VPN server. Place your CA files on a storage which can be offline as much as possible, only to be activated when you need to get a new certificate for a client or server.
The files you need to copy out from a CA are just 3 files for each client and server.
- Private key (often a .key or .pem file)
- Certificate (often a .crt or .pem file)
- CA certificate (also a .crt or .pem file)
The server in addition needs a DH parameters file. This can be generated by using OpenSSL:
$ openssl dhparam -out dh2048.pem 2048
The 2048 bits indicate the size of the DH prime number. Typically, a 2048-bit size offers sufficient security as of October 2015. Ideally, the length of the DH prime number should match the RSA key length. For example, if you are using a 4096-bit RSA key, it is recommended to use DH parameters of 4096 bits.
BEWARE: Avoid generating keys on devices lacking a good entropy source for generating random data. This includes many common Wi-Fi routers and similar embedded devices. Often, virtual machines may also lack a good entropy source, or it could be manipulated by the hypervisor. Whenever possible, generate keys and DH parameters on bare-metal equipment.
For a better understanding of how PKI works, check out this introduction: Intro to PKI
Now, let's use these key and certificate files in the OpenVPN configuration files.
Server configuration:
tls-server key server-key.pem cert server-crt.pem ca ca-crt.pem dh dh2048.pem remote-cert-eku "TLS Web Client Authentication"
Client configuration:
tls-client key client-key.pem cert client-key.pem ca ca-crt.pem remote-cert-eku "TLS Web Server Authentication"
This setup provides a secure baseline for an OpenVPN client and server communication. Using certificates adds a preliminary layer of authentication. Only clients with a certificate signed by the CA in ca-crt.pem will be accepted by the server. Similarly, the client will verify that the server's certificate is signed by the CA listed in its local ca-crt.pem.
The --remote-cert-eku option is optional but highly recommended. It ensures the server verifies that the client's certificate is genuinely for a client, and similarly, the client verifies the server's certificate is for a server. Without this, an OpenVPN server could potentially use a client certificate to act as a server.
The --tls-server and --tls-client options are used to specify that OpenVPN will act as a server or client with TLS layers activated. These options are necessary for --key, --cert, and --ca to be recognized.
Certificates and private keys are used primarily to secure the exchange of a temporary encryption key for the OpenVPN session. This temporary key, stored only in RAM, encrypts data transmitted over the VPN connection, also known as the data channel.
The encryption algorithm for the data channel can be changed. OpenVPN supports the same algorithms as your SSL library. To see available algorithms, use:
$ openvpn --show-ciphers
Ciphers listed with '(variable)' in the output have a variable key length, which can be adjusted with the --keysize option.
WARNING: By default, OpenVPN uses the Blowfish cipher, which is now discouraged due to vulnerabilities in Blowfish, RC4, CAST5, and DES/3DES. If you must use these weaker algorithms, consider adding --reneg-bytes 64000000 to your configuration. If your server version is >= 2.3.14 or 2.4.1, this adjustment is made automatically. For more information, see SWEET32.To use the preferred AES algorithm with 256 bits encryption, add this line to both client and server configs:
cipher AES-256-CBC
For most initial VPN setups, starting with Blowfish provides a fairly good security level. However, remember that once you decide to upgrade your ciphers, you need to modify all server and client configs to the same --cipher value.
You can do another step to strengthen the encryption layer. The temporary session key was already mentioned, which is used for encrypting the tunneled network data. This key will rotate by default every hour. But you can also tweak how often it gets rotated by adjusting --reneg-sec, --reneg-pkts, and --reneg-bytes. See the OpenVPN man page for more information about these options.
Configuring authentication
There are several more authentication layers which can be added in OpenVPN on top of the basic one which certificates provide. The authentication layers in this section are purely optional. But it is advisable to add at least one or more of them.
TLS Authentication
This is kind of like a crypto firewall. Each packet going over the Internet will be signed using a shared secret on both servers and clients. When OpenVPN receives a packet, it will calculate a signature and check it against the signature provided in the received packet. If it doesn't match, OpenVPN will drop the packet. When coupled with UDP, this can also be a good way to avoid troubles with port scanners; as it will not see the OpenVPN port at all. This feature is also a good way to protect yourself against unknown bugs in the SSL library or protocol, as it reduces the attack surface to only your own users. Enabling TLS authentication is HIGHLY recommended.
To enable TLS authentication, first generate a static encryption key. This needs to be securely copied to all OpenVPN clients and servers.
$ openvpn --genkey --secret myvpn.tlsauth
In the configuration files, you need to add:
tls-auth myvpn.tlsauth KEYDIR
The KEYDIR must be 0 on one of the sides and 1 on the other. So if you choose the KEYDIR value of 0 for the server, all clients must be 1, and vice versa.
If you are using OpenVPN v2.4 or later, you can make this even a bit stronger by replacing --tls-auth with --tls-crypt. Using tls-crypt also doesn't need to care about the KEYDIR - that is handled automatically.
tls-crypt myvpn.tlsauth
Please note that you cannot use --tls-crypt and --tls-auth at the same time.
Username / password authentication
There exist many methods for adding username/password authentication. There are plenty of plug-ins and scripts for PAM, LDAP, Radius, and so on. There are also more advanced authentication and access controls available, such as the eurephia project. We will not cover any of these setups here.
Even stricter certificate checks
It is also possible through a plug-in or the --tls-verify script hook to add additional checks on certificates. This can also protect you somewhat better if you lose control over your CA private key, if you check the client certificate's fingerprint/digest against a local database you have collected.
push "ifconfig 10.8.0.2 255.255.255.0"
This command tells the server to push this specific IP configuration to the client when it connects. This configuration sets the client's IP to 10.8.0.2 and the subnet mask to 255.255.255.0.
Advanced IP Address Configuration
For more complex setups, you might want to manage the IP addresses more dynamically. This can be done using a combination of server-side scripts or integrating with an existing DHCP server that handles IP assignments. This setup is beyond the scope of this basic tutorial but is well-documented in the OpenVPN community resources.
Finalizing the Network Configuration
Once the virtual network device and IP addresses are configured, you should ensure that the server is routing traffic correctly. This can involve setting up NAT (Network Address Translation) if the clients need access to the internet through the VPN server. Add this to the server configuration:
push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 8.8.8.8"
These lines configure the client to route all traffic through the VPN (including internet traffic) and use Google DNS for name resolution.
Testing Your Configuration
After setting up the network layer, test the configuration by connecting a client to the server and checking if it can reach the internet and other network resources as expected. Use tools like ping and traceroute to verify connectivity and correct routing.
Remember, each network is unique, so adjustments to these configurations might be necessary to fit your specific requirements. Always ensure your configurations are secure and tested thoroughly in a controlled environment before deploying in a production scenario.
topology subnet server 10.8.0.0 255.255.255.0
This sets up a VPN subnet using the 10.8.0.XXX address scope. The server will become 10.8.0.1, and the first client will start at 10.8.0.2. This is due also due to that we set OpenVPN to use the subnet topology. This is the recommended OpenVPN setup and behaves more closely to traditional networks.
In the client configuration, you need to add:
topology subnet pull
This tells the client that the server uses the subnet topology and that it should use the IP address and routing the VPN server provides.
At this point, it should be possible to start up both the server and client. They should be able to connect and from the VPN client you should be able to ping 10.8.0.1 and from the server side you should be able to ping 10.8.0.2.
If you want to access particular network resources on other IP addresses via the VPN tunnel, you need to add network routes. A network route tells your operating system where it needs to send the network traffic when you want to access certain resources. An operating system can handle multiple routes via multiple gateways at the same time. So if you have a server on 192.168.1.10 behind your VPN server and you want to access this server via the VPN, you need to tell OpenVPN to configure a route for either a specific host or a network range to go via the tunnel.
So to configure this, you need to add one line in the server configuration and restart server and client.
push "route 192.168.1.0 255.255.255.0"
When the client now connects, the server tells the VPN client that it should route all traffic for IP addresses in the 192.168.1.XXX scope via the VPN connection.
This is a very basic setup. And when we now start on the routing part, the VPN setup is mostly done. All you need now is to add the needed routes you need, just like you would do for normal TCP/IP routing.
BEWARE: Remember that you also need to consider what is called "return routes". If your VPN client can access a host behind your VPN server, it does not mean that the host behind the VPN server will send the response via the same route. So you need to ensure that your hosts behind your VPN server also know which gateway to use for your VPN. Nowadays this is most commonly fixed by adding a route on your existing default gateway. And if you run OpenVPN on an existing gateway, you have this return route already implicitly configured.
For a more detailed example using routing, see the Using routing section in the 'Bridiging and routing' wiki page.
Routing everything over the VPN
It is possible to route absolutely all network traffic over the VPN. The configuration in OpenVPN is fairly simple. But you will need to investigate how to configure NAT on your VPN server for the virtual tun adapter.
You can either push such a "route everything over VPN" via the server, or you can add it explicitly in the client configuration. Do not use both at the same time.
Server push:
push "redirect-gateway def1"
Client configuration alternative:
redirect-gateway def1
What about IPv6?
OpenVPN v2.3 and later supports IPv6. To set up IPv6 in the tunnel is pretty much the same as for the IPv4 examples we already have covered. You need to use the --server-ipv6 and --route-ipv6 options to configure IPv6.
For example, adding this will configure the IPv6 addresses for server and clients:
server-ipv6 2001:db8:cada::/64
You can use the --route-ipv6 option, either pushing it from the server or using it directly in the client configuration, just as you can with the --route option. The syntax is similar too:
route-ipv6 2001:db8:daca::/64
Other aspects to consider when configuring a VPN
There are a few more things which may need to be configured, but those are mostly outside of OpenVPN. The most common issues are related to adjusting your operating system to allow forwarding of packets and configuring the firewall properly.
On most Unix/Linux based operating systems, setting up IP forwarding is just a matter of doing:
sysctl net.ipv4.ip_forward=1 sysctl net.ipv6.conf.all.forwarding=1
These values are reset upon boot, so they can also be stored in /etc/sysctl.conf to be enabled at boot.
Configuring the firewall is so different between Linux and other Unix-based OSes, in addition several Linux distributions have their own tools to manage iptables. So, it is better to read the manuals for the firewall configuration on your operating system.
