OpenVPN Server Configuration on Debian Linux

Why Set up OpenVPN on Linux?

OpenVPN server configuration may seem difficult on first glance. However, with the proper knowledge it is actually easy. Within about fifteen minutes you can build a tunnel. The ability to safely construct a tunnel between your devices outside the network and the devices within your network cannot be overstated. A VPN allows you the flexibility to quickly deploy your own self-hosted software without worrying about port forwarding or routing.

My Own OpenVPN Server Configuration

To provide an example, I have my own OpenVPN network running on an ancient Core2Duo computer in my house. Using this machine I have built myself an entire cloud platform. I am able to read e-books, stream music and movies, access my own cloud storage using Samba and communicate with my friends using hardware I own. Prior to deploying OpenVPN, I relied heavily on port forwarding through my firewall.

This lacked the security and extensibility that a VPN provides. I grew tired of having to go out of my way to configure domains for each and every single service I deployed just so I could get an X.509 certificate from Let’s Encrypt. I found it extremely tedious trying to keep up with my constantly shifting firewall needs.

Eventually, I took the plunge into VPNs and never looked back. I originally utilized Wireguard, but as time goes on I’ve been moving more heavily to OpenVPN. The biggest factor which convinced me to switch was the much better debugging facilitates. I found troubleshooting non-functional connections in Wireguard to be very tedious. By comparison, OpenVPN has a very clean and easy to read logging format. It allows for ten levels of verbosity which means that you have detailed logs when you need them. When you don’t, you can reduce this number and get just the information you need.

This tutorial will walk you through the process of OpenVPN server configuration. It’s relatively short and should only take ten or fifteen minutes.

Prerequisites

OpenVPN is fairly light on prerequisites. While I am writing this tutorial while on Debian Buster, the same steps should work on other Linux distributions. It should even be possible to set it up on Windows or Mac OSX. In these two cases, some of the steps will be different however.

Initial Installation

The first step is to install OpenVPN on your Linux distribution. For Debian, this involves the use of the apt utility. While installing the openvpn package, make sure to also install the easy-rsa utility. This greatly eases the burden of configuring the X.509 infrastructure which you will need to set this server up correctly.

sudo apt install openvpn easy-rsa

Now that the packages are installed, we need to add Easy-RSA to the system’s path. Doing so will allow us to invoke it without moving it from the package’s installation directory. Open up ~/.bashrc in your favorite editor and add the following:

PATH=$PATH:/usr/share/easy-rsa/
Code language: JavaScript (javascript)

Now, source the file. We should now have access to Easy-RSA by simply running “easyrsa”.

What is a Public Key Infrastructure?

You may be asking yourself “What is a Public Key Infrastructure?” A PKI is the first part of an OpenVPN Server Configuration. It controls the generation and distribution of cryptographic keys which allows your VPN to work. If your server lacks the right files, the VPN will not accept connections. Equally, if your clients do not have the right keys, they will fail to connect.

This infrastructure is what makes VPNs so powerful. No systems can connect to the server unless they have the proper credentials. The files which will be on each machine can be thought of as an extremely long password. This means that trying to crack one of these files is nearly impossible, even with a rainbow table. When paired with a strong cryptographic algorithm such as AES-256-CBC, all traffic that passes over this network will be not be able to be snooped on.

Configuring the Public Key Infrastructure

To get started, we need to start by generating the public key infrastructure. As discussed before, Easy-RSA greatly simplifies the process. We will only have to directly interface with OpenSSL for a single command. There are many steps to producing this infrastructure. It can be very time consuming if done by hand.

How Our Infrastructure Will Look

It ‘s very important to have a solid grasp on how the public key infrastructure should look. Forgetting to include even one of these files will result in a server that does not function properly.

OpenVPN Server Configuration PKI Files

  • ca.crt – This is the cryptographic certificate for the “signing authority”. In this tutorial, the signing authority and OpenVPN server are the same machine. This is not always the case. HTTPS utilizes X.509 as well. When you get a certificate to enable HTTPS on your site, the signing authority is the company from whom you are getting the certificate. Let’s Encrypt is an example of this.
  • server.crt – This is the certificate for the server itself. The information contained within this file will be verified by all clients connecting to the server.
  • server.key – This is a secret file which must never be shared outside the server. This key prevents third parties from impersonating your server. If they are able to get access to this file then they can deploy their own server and your clients would connect to it, thinking it is yours.
  • ta.key – This file makes up what is called the “HMAC signature”. While not strictly required, this provides an additional layer of security. clients lacking this file will be cut off from connecting to your server before they even have a chance to authenticate. This helps prevent certain DDOS attacks.

OpenVPN Client(s)

  • client.crt – While not actually called client.crt in this tutorial, this file is the certificate for the client.
  • client.key – The key for the client’s certificate. This must be kept safe, lest an attacker successfully impersonate the client in question.
  • ta.key – This file is identical to the one on the server. It allows clients to successfully get past the HMAC signature check.

EasyRSA Makes OpenVPN Easy

Deploying an X.509 infrastructure directly through OpenSSL is hard. There are many steps and doing them out of order may break the process entirely. To make this process easier, OpenVPN has a set of bash utilities known as Easy-rsa.  Easy-rsa allows you to easily generate everything you need to build a complete PKI.  This utility generates everything from certificates and keys to the HMAC key and certificate revocation list can be generated through this utility.

Begin Generating the OpenVPN Server PKI

The first thing we need to do is generate the directory which will hold the PKI. The following command will do so.

easyrsa init-pki

Setting Defaults for Easy-RSA

Now that the directory has been generated, we need to configure the variables which will be embedded within the generated certificate. The vars file allows us to do so. Let’s go ahead and copy the example provided with Easy-RSA. Run the following command to copy the example provided with Easy-RSA.

cp /usr/share/easy-rsa/vars.example ./pki/vars

Let’s configure some default settings for Easy-RSA.  These settings make up the information included in the certificates we are generating.  Open ./pki/vars and add the following to the bottom:

set_var EASYRSA_REQ_COUNTRY "<Your Country>" set_var EASYRSA_REQ_PROVINCE "<Your State>" set_var EASYRSA_REQ_CITY "<Your City>" set_var EASYRSA_REQ_ORG "<Your Organization>" set_var EASYRSA_REQ_EMAIL "<Your Email>" set_var EASYRSA_REQ_OU "<Your Organizational Unit>"
Code language: HTML, XML (xml)

During the setup you will need to additionally fill out the common name.

Copy the OpenSSL Configuration File

Now, we need to copy OpenSSL’s example configuration file for Easy-RSA.

cp /usr/share/easy-rsa/openssl-easyrsa.cnf /etc/openvpn/openssl-easyrsa.cnf

First Step: Generating the Certificate Authority For the OpenVPN Server Configuration

The first piece of a public key infrastructure is the certificate authority. This certificate authority is a trusted third party which vouches for both the client and server.  It signs both of the two parties’ certificates so that they can be validated during a connection.  In this  case, we’re going to be our own certificate authority. The same machine that runs the OpenVPN server will also sign both of the keys.  This will give us the ability to sign the certificates on our own machine without having to take them to an outside source.  Run the following command to do so:

easyrsa build-ca nopass

Fill out the common name and wait for the certificate generation to complete. After this you will have both the certificate signing request and its associated key. In the next step, we will validate this request and produce the actual certificate.

Second Step: Generate the Server Certificate and Key For the OpenVPN Server Configuration

Now we need to  generate a certificate and key for the server.  We will use the certificate we generated in the last step to do so.   This is a three step process.  The first thing we have to do is to generate a signing request for the server.  The following command will do so:

easyrsa gen-req server nopass

The certificate authority must take this request and sign it to generate the final server certificate. To continue the process, let’s go ahead and sign the request.

easyrsa sign-req server server

Note: If you receive a message saying “Unknown cert type ‘Server'”, copy the x509-types/ directory into the folder you created to hold the generated files

cp -r /etc/easy-rsa/x509-types/ ./

Easy-RSA’s sign-req server command will utilize our certificate authority ca.cert file to sign the server.crt file and configure it for use by an OpenVPN server.

We now have the server’s certificate generated. This is just the first step of the process. We have functional credentials for the server, but without equivalent files for clients, this won’t get us very far.

Third Step: Generate the Client Certificate and Key For the OpenVPN Server Configuration

Now, let’s go ahead and generate our first client keypair. The two files will need to be distributed to the client machine either via SFTP, Samba, USB, or other means.

easyrsa build-client-full client1 nopass

This will automatically run through the same steps for a client certificate and key.  it will automatically sign them as well.

Fourth Step: Generate the Diffie-Hellman Parameters For the OpenVPN Server Configuration

Diffie-Hellman parameter establish perfect forward secrecy.  This creates a new session for each new connection.  In this way, a compromised key will be unable to decrypt prior communications. Keep in mind that this step will take some time. The ./pki/dh.pem file will be included in the config file used by the server later.

easyrsa gen-dh

OpenVPN Server Configuration Files

With that out of the way, we’re now going to perform the basic configuration needed to get OpenVPN off the ground.  Go ahead and open up /etc/openvpn/server.conf and make the following changes:

# Specify the protocol and port the server will use. # Routing TCP over TCP is very inefficient due to the packet checks it performs. proto udp port 1194 # Provide the server with the files it needs to perform X.509 handshaking. ca /etc/openvpn/pki/ca.crt cert /etc/openvpn/pki/issued/server.crt key /etc/openvpn/pki/private/server.key dh /etc/openvpn/pki/dh.pem # Certificate Revocation List #crl-verify /etc/openvpn/pki/crl.pem # Determine the type of virtual device used on the server. # tun utilizes layer 3 routing. It is the most compatible. # tap utilizes layer 2 routing. It is necessary when protocols not TCP/IP based # need to be routed. dev tun auth SHA512 cipher AES-256-CBC topology subnet server 172.16.0.0 255.255.0.0 tls-auth /etc/openvpn/pki/ta.key 0 # Data compression with compatibility for older clients. comp-lzo # Makes the OpenVPN server drop root privileges when no longer needed. # This is a very good idea. user nobody group nobody # Useful for debugging. The higher the number, the more verbose the output. verb 3 log-append /var/log/openvpn.log #https://v13.gr/2014/09/11/openvpn-and-remote-cert-tls-server/ #remote-cert-tls server
Code language: PHP (php)

Forwarding Traffic Through the Server

The first setting we’re going to configure gives us the ability to route all of the clients’ traffic through our server.  This allows it to work very similarly to anonymizing VPNs and is useful for providing Internet access through the network. Add the following to server.conf.

push "redirect-gateway def1 bypass-dhcp"
Code language: JavaScript (javascript)

This option is not necessary if the VPN does not need to provide access to the Internet.  Clients on the virtual private network will happily use the network by itself and continue to use their own default gateway.

Configuring DNS For Clients

Next, set the configuration to pass DNS server addresses to the clients.  This is necessary to ensure that they maintain Internet access once connected.

push "dhcp-option DNS 208.67.222.222" push "dhcp-option DNS 208.67.220.220"
Code language: CSS (css)

Topology of the OpenVPN Server

The subnet topology represents a standard spoke and wheel type network configuration.  This allows much more flexibility in configuration.  Any number of clients can connect and communicate as if they were all hooked to the same switch.  In contrast, legacy versions of OpenVPN only support a “net30” configuration.  This configuration creates a /30 network.  This greatly limits the maximum number of clients and makes routing between large groups of devices much more difficult.  The one caveat in both of these schemes is that all data must flow through the VPN server, which could potentially become a bottleneck and single point of failure.

Security Hardening

Dropping Root

By default, OpenVPN will run as root.  The following lines in server.conf will make it drop the privileges once no longer needed.  This way, an exploited flaw in the OpenVPN software will provide a hacker with little additional access.

user nobody group nobody

One of the steps we will take to secure our server is to instruct the server to validate the certificates of any client connecting.  The following configuration option will do so:

remote-cert-eku "TLS Web Client Authentication"
Code language: JavaScript (javascript)

Enable HMAC Authentication

The next step we will take is to enable an additional layer of HMAC verification for all encrypted handshake packets sent through the tunnel.

Add the following to the bottom of /etc/openvpn/server.conf:

tls-auth ta.key 0
Code language: CSS (css)

Now we need to actually generate this key.

sudo openvpn --genkey --secret /etc/openvpn/pki/ta.key

Virtual Network Configuration

First, allow OpenVPN through your firewall.

sudo firewall-cmd --get-active-zones sudo firewall-cmd --zone=trusted --add-service openvpn --permanent sudo firewall-cmd --list-services --zone=trusted sudo firewall-cmd --add-masquerade sudo firewall-cmd --permanent --add-masquerade SHARK=$(ip route get 8.8.8.8 | awk 'NR==1 {print $(NF-2)}') sudo firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 \ -o $SHARK -j MASQUERADE sudo firewall-cmd --reload
Code language: PHP (php)

Now edit /etc/sysctl.conf and add the following:

net.ipv4.ip_forward = 1

Now restart the networking service:

sudo systemctl restart network.service
Code language: CSS (css)

Next, enable and start OpenVPN on the server:

sudo systemctl enable openvpn@server.service sudo systemctl start openvpn@server.service
Code language: CSS (css)

Client Configuration

Copy the following files from the server to the client:

/etc/openvpn/easy-rsa/keys/ca.crt /etc/openvpn/easy-rsa/keys/client.crt /etc/openvpn/easy-rsa/keys/client.key /etc/openvpn/myvpn.tlsauth

Create a file on the client called client.ovpn containing the following:

client tls-client ca /home/pdreyer/OpenVPN/keys/ca.crt cert /home/pdreyer/OpenVPN/keys/client.crt key /home/pdreyer/OpenVPN/keys/client.key tls-crypt /home/pdreyer/OpenVPN/myvpn.tlsauth remote-cert-eku "TLS Web Client Authentication" proto udp remote <Your IP> dev tun topology subnet pull user nobody group nobody
Code language: HTML, XML (xml)

Now start the OpenVPN client:

sudo openvpn --config ~/path/to/client.ovpn
Code language: JavaScript (javascript)

Conclusion

With that, our OpenVPN server configuration is complete. I hope very much that this tutorial has helped you. If you have any questions or concerns, please feel free to leave a comment and I’ll gladly respond.

Leave a Reply

Your email address will not be published. Required fields are marked *