= OpenVPN - Getting started How-To = Setting up a VPN based on OpenVPN requires setting up a few "groups" of configuration options. Each of them covers separate elements of a VPN tunnel. One part is the connection between server and clients. Next up is the encryption layer, then there is the authentication layer and at the end we cover the network inside the tunnel. One nifty detail about OpenVPN configuration options. Almost all of these options can be used either on the command line directly or via a configuration file. The main difference is that on the command line you must use two leading dashes (--) for OpenVPN to understand what you mean. When using these options in the configuration file must not use any leading dashes at all. When starting OpenVPN, you can either use the --config option to tell OpenVPN which configuration file to use. Or if you do not use any options at all, you can just provide the file name directly. {{{ # openvpn --config myvpn.conf # openvpn myvpn.conf }}} Notice that you can use --config multiple times, to merge several configuration files. Or you can use 'config' inside a configuration file to "include" another configuration file. == Setting up the connection == You must first of all decide if you want to use UDP or TCP for connections. Generally speaking, UDP is the preferred alternative in most cases. If you cannot get a reliable UDP connection, then you might need to look into TCP. The reason for avoding TCP can be found here: http://sites.inka.de/bigred/devel/tcp-tcp.html Using UDP requires just to add {{{ proto udp }}} in both client and server configurations. For TCP, the server requires {{{ proto tcp-server }}} and the client requires {{{ proto tcp-client }}} Then a port number is needed. The official OpenVPN port number is 1194, but any port number between 1 and 65535 will work. If you don't provide the 'port' option, 1194 will be used. An example using port 443 {{{ port 443 }}} In the client configuration you need to tell where to connect. Both hostnames and IP addresses can be used. {{{ 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 blocks, read more about that in the [wiki:Openvpn24ManPage 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 '''can not''' 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`/`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 [wiki:StaticKeyMiniHowto 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 any where 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. https://github.com/OpenVPN/easy-rsa/blob/master/doc/EasyRSA-Readme.md '''BEWARE:''' One common mistake when setting up a new CA is to place all the CA files on the OpenVPN server. [[span(style=background: #FFD0D0;padding-left: 6px; padding-right:6px;, 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 loose 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 the OpenSSL: {{{ $ openssl dhparam -out dh2048.pem 2048 }}} The 2048 indicates how many bits the DH prime number should consist of. The value of 2048 bits should in most cases be secure enough (as of October 2015), but it is ideal to have the DH prime number length to match the length of the RSA key. So if your key is 4096 bits, it is advisable to have 4096 bits DH parameters. BEWARE: You should avoid generating keys on any devices which does not have a good entropy source for random data. This includes most of the common wifi routers and similar embedded devices. In many cases virtual machines also does not have a good entropy source or it can be manipulated by the hypervisor. Try as far as possible to generate keys and DH parameters on bare-metal equipment. To better understand how PKI work, have a look at this introduction: https://github.com/OpenVPN/easy-rsa/blob/master/doc/Intro-To-PKI.md Now we need to make use of these key and certificate files in the OpenVPN configuration files. Server config: {{{ tls-server key server-key.pem cert server-crt.pem ca ca-crt.pem dh dh2048.pem remote-cert-eku "TLS Web Client Authentication" }}} The client config need to look something like this: {{{ tls-client key client-key.pem cert client-key.pem ca ca-crt.pem remote-cert-eku "TLS Web Server Authentication" }}} This provides a fairly good and secure starting point for an OpenVPN client and server to start talking to each other. And when certificates are used, the first level of authentication is already added. Only clients with a certificate signed by the CA identified in ca-crt.pem will be accepted on the server. And the client will also authenticate that the server certificate is signed by the CA the client has in its local ca-crt.pem file. The --remote-cert-eku is optional, but highly recommended. It ensures that a server will verify that the client certificate provided is truly a client certificate, and vice versa for the client which checks that the server certificate truly aimed for a server. Otherwise, an OpenVPN server can use a client certificate acting as a server. We can add a few more hardening steps, but will come back to that later on. And then there is the --tls-server and --tls-client options. They are just used to tell OpenVPN that it will act as a server or client with the TLS layers activated. Those options are needed for --key, --cert and --ca to be accepted. With this in place, the certificates and private keys are actually just used to secure the exchange of a temporary encryption key for the OpenVPN session. This temporary encryption key (which you will not see for yourself; it will be in RAM only) is used for encrypting the data which will be passed over the VPN connection, also known as the data channel. So all your network traffic between your server and client goes in the data channel and will be encrypted by this temporary key. The encryption algorithm which is used for the data channel can be modified as well. OpenVPN mostly provides the same algorithms as your SSL library supports. To see which algorithms are available, see the outpout of: {{{ $ openvpn --show-ciphers }}} Those ciphers which are listed with '(variable)' in the output can have a variable key length, controlled by the --keysize option. '''WARNING:''' By default OpenVPN does currently use the Blowfish cipher, but that is now discouraged due to general issues with Blowfish, RC4, CAST5 and DES/3DES. If you need to use any of these weaker algorithms, do at least consider to add `--reneg-bytes 64000000` to your configuration. If your server version is >= 2.3.14 or 2.4.1 this will be done for you. For more information see [wiki: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. But 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 tunnelled 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 [wiki:Openvpn24ManPage 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 provides. The authentication layers in this section is 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 don'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 exists many methods for adding username/password authentication. There exists 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 loose control over your CA private key, if you check the client certificate's finger print/digest against a local database you have collected. For client configurations you can also easily add --verify-x509-name, where you provide for example the certificate subject of the server. This will ensure that only a server who identifies itself as a particular server will be accepted. For example like this: {{{ verify-x509-name 'C=US, O=Test CA, CN=myvpn.example.com' subject }}} You can also just check against the CN attribute in the subject: {{{ verify-x509-name myvpn.example.com name }}} === Adding certificate revocation lists === Within the CA, you can also revoke certificates as needed. Using the CA management tool of your choice, you should be able to generate a Certificate Revocation List (CRL file). By adding this to the OpenVPN server, all client certificates will be checked against this revocation list. Clients which have their certificates listed in the CRL will not be able to connect. This is a common way to disable access to a VPN service on a per user level. Add this line to the OpenVPN server configuration: {{{ crl /full/path/to/crl.pem }}} == Configuring the network layer == So far we've covered getting a connection between an OpenVPN client and server and the server and client have authenticated each other through various methods. So the client and server can now communicate, but they have no idea what to do with the network. So lets configure that. First we need to setup a virtual network device. OpenVPN supports two types of such devices, TUN and TAP. The difference is that TUN only passes TCP/IP traffic and does not provide any broadcast traffic across the VPN tunnel. This provides a fairly efficient tunnel with the lowest overhead. For more advanced setups the TAP device may be used, which is also able to transport other protocols than just TCP/IP. TAP mode transports Ethernet frames instead of just IP packets. So there are many ways to configure the network layer in OpenVPN. The general recommendation, and the one we will cover here, is what is often called "routed tun". That means we use a tun device and use traditional TCP/IP routing techniques. For an overview of TAP mode and bridging vs routing, see the [wiki:BridgingAndRouting Bridging and Routing] page for more information. To configure a tun device, just add this line to both client and server configurations: {{{ dev tun }}} You can also provide a specific tun device, for example tun0 instead of tun. But if the 'tun0' device is already configured, OpenVPN will fail. It is also possible to use your own name for the virtual network device, but you then need to use --dev-type in addition. {{{ dev myvpn dev-type tun }}} BEWARE: The device type must be identical on server and clients. You cannot use TAP on clients and TUN on servers or vice versa. Next we will need to configure IP addresses. In this How-To we will push the IP address the client should use from the server to the client, as that is the simplest setups. In the server configuration add this line: {{{ 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 toplogy. This is the recommend OpenVPN setup and behaves more closer 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 knows 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 impllicitly configured. For a more detailed example using routing, see the [https://community.openvpn.net/openvpn/wiki/BridgingAndRouting#Usingrouting 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 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.