Running an VPN server on your local area network will allow outside clients to connect to your server and access the network as if they were directly connected to it. This is a common setup for many companies, which let their employees connect to the local business network remotely, so that they have access to internal resources that are only available on the local network. Linux administrators and power users may also be interested in setting up an VPN server at home, since they can then use their laptop or other portable device to connect to their home network while on the go.
One of the best implementations of a VPN system is OpenVPN. It is completely open source and supports many features for customization. In this tutorial, we will go through the step by step instructions of installing and setting up OpenVPN on a Linux system. This will include installation of Easy-RSA for CA and client certificates. Then, we will show how to use a client system to connect to the VPN server and begin accessing the local network of the server. Follow along with us below to get started.
Privileged access to your Linux system as root or via the sudo command.
Conventions
# – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command $ – requires given linux commands to be executed as a regular non-privileged user
Setting Up a Certificate Authority
First, we will set up the system that we plan on using for the certificate authority (CA). Follow the step by step instructions below to finish the CA server:
First, install the Easy-RSA package. This will be the tool that we use in order to generate a private key which will then sign requests from incoming client connections that need the CA to verify the identity of the OpenVPN server. On debian and ubuntu based systems:
$ sudo apt install easy-rsa
On Fedora based systems:
$ sudo dnf install easy-rsa
Next, let’s get started with configuring Easy-RSA. We will do this by creating a directory for our Public Key Infrastrucure (PKI). This can be named whatever you want, but we will keep it straightforward for the sake of example:
$ mkdir ~/easy-rsa
Next, we can either copy all the Easy-RSA files into our new PKI directory, or just create a symbolic link to them. The advantage of creating the symbolic link is that we will not need to modify our PKI directory in case there are future updates to the Easy-RSA package. Execute the following command to create the link:
$ ln -s /usr/share/easy-rsa/* ~/easy-rsa/
$ cd ~/easy-rsa
Once we are in the ~/easy-rsa directory, we run the script that initializes it as a PKI directory.
After editing the file to your satisfaction, save changes and exit it.
Next, we will run the build-ca script. This will build the Certificate Authority, which generates a public and private key pair.
$ ./easyrsa build-ca
You will be prompted to enter a passphrase that secures the key pair. Then, enter a name that represents your CA server, such as the hostname or username. We use linuxconfig-CA in the screenshot below:
Your server is now ready to act as a Certificate Authority. All clients that need to interact with your CA will need a copy of the ca.crt file, which should be stored in the ~/easy-rsa/pki directory, if you have been following along with us.
$ cat ~/easy-rsa/pki/ca.crt
It is up to you how you choose to distribute the file, but all VPN clients will need a copy of it.
OpenVPN and Easy-RSA Installation
Now we move over to the VPN server. This is where we will install the VPN server software, while the CA server we configured in the previous section will be resposible for issuing or revoking certificates.
The first step is to install the OpenVPN software and Easy-RSA. These can be easily installed via official repositories on all major Linux distros. You can use the appropriate command below to install OpenVPN and Easy-RSA with your system’s package manager.
We will now begin setting up the VPN server. The first few steps will look familiar, as we have to repeat some things that we also did on the CA server. Let’s get started.
First, create the easy-rsa directory as we did before, and create a symbolic link it to the installed files.
These are the recommended security settings for both maximum speed and security. You can, of course, change them as you see fit.
Inside of the ~/easy-rsa directory, we run the script that initializes it as a PKI directory.
$ ./easyrsa init-pki
Next, we will generate a private key for the VPN server, as well as a Certificate Signing Request (CSR). In later steps, this request will need to be signed by the CA that we configured earlier. Take a look at the following command syntax:
$ ./easyrsa gen-req linuxconfig-server nopass
Here, we are passing the gen-req option to the easyrsa script. Then, we pass a name for our VPN server, which will be linuxconfig-server. Lastly, the nopass option will get rid of password protection on the request file, which simplifies the entire process.
Now we need to copy the VPN server’s private key to the OpenVPN directory. The output from the previous command should tell you the full path to your private key. In our case, the following command is used:
You would need to replace linuxconfig-server.key with the name of your own private key.
The next step is to transfer the CSR over to the CA server for it to be signed. You can transfer the file over however you would like, for example with the scp command.
Switching to the CA server now. Now that the .req file is transferred over to the CA server, we will import it and then sign the request:
$ cd ~/easy-rsa
$ ./easyrsa import-req /tmp/linuxconfig-server.req linuxconfig-server
$ ./easyrsa sign-req server linuxconfig-server
Make sure you substitute your own common names where necessary. Ours is simply linuxconfig-server. You will also be prompted for the password that we configured earlier on the CA server.
Now we need to transfer the ca.key and linuxconfig-server.crt files from the CA server back to the VPN server. Use scp or your preferred method to do so:
Switching back to the VPN Server now. On the VPN server, take the files out of the /tmp directory that we just transferred and place them in the /etc/openvpn/server directory. You will need root permissions to move them:
As a final security measure, we can generate a tls-crypt pre shared key. This boosts the security for the OpenVPN server and makes it easier to process incoming traffic.
$ cd ~/easy-rsa
$ openvpn --genkey secret ta.key
Copy the generated ta.key file over to the /etc/openvpn/server/ directory:
$ sudo cp ta.key /etc/openvpn/server
Now we are ready to move on to generating certificates and keys for each client that will be connecting to the VPN.
Generate Certificates and Keys for Clients
These steps will be performed on the VPN server, until we eventually switch over to the CA server, which will be clearly indicated. You will need to repeat these steps for each VPN client. This is where some Bash scripting might come in handy, in case you want to help automate the process in the future.
First, let’s create a directory where we will be storing the keys for the clients.
$ mkdir ~/client-keys
Navigate to the Easy-RSA directory, and then use the easyrsa script to generate a request for a client. In this example, our client will be named linuxconfig-client. Change yours as needed:
$ cd ~/easy-rsa
$ ./easyrsa gen-req linuxconfig-client nopass
You will be prompted for the CA password that was configured in earlier steps. This should all look familiar, as the process is pretty much the same as when we signed the CSR for the VPN server.
OpenVPN has various example files that can be used to get a jumpstart with your own VPN server configurations. We will use one of these files and begin to customize it for our needs. You can also apply your own customizations along the way, but some of the suggestions seen below will be necessary to apply in order to work with the previous configuration we have set up.
Note that the following steps are to be performed on the VPN server.
We will start by taking the server.conf example file from the OpenVPN documentation and copying it over to the /etc/openvpn/server directory.
We will need to configure this file to use the TLS certificate that we made earlier. Locate the following line and comment it out by adding a ; character in front of it:
tls-auth ta.key 0 # This file is secret
Below that, add the following line:
tls-crypt ta.key
The final result should look like:
;tls-auth ta.key 0 # This file is secret
tls-crypt ta.key
Next, locate the following cipher line and comment it out:
This will force our VPN connection to use better encryption than the default config.
Since we have configured our VPN server to use ECC (Elliptic Curve Cryptography) instead of DH (Diffie-Hellman), we will need to locate the following dh line and comment it out:
dh dh2048.pem
Right below that, add the following line:
dh none
The final result should look like this:
;dh dh2048.pem
dh none
To reduce the OpenVPN daemon’s privileges when it is initialized, and therefore reduce its potential attack surface, locate and uncomment the following lines:
;user nobody
;group nobody
Remove the ; in front of them, so that it reads:
user nobody
group nobody
If you want to reroute all client traffic through the VPN, then you can locate the following line and uncomment it:
;push "redirect-gateway def1 bypass-dhcp"
Be sure to remove the preceding ; to uncomment it.
This is not strictly necessary but it is the behavior that most VPNs use, so it is what clients will expect.
Uncomment the following lines that give the VPN clients some DNS servers to use for name resolution. These are the IPs to OpenDNS servers, but you can put any DNS server IPs you want:
;push "dhcp-option DNS 208.67.222.222"
;push "dhcp-option DNS 208.67.220.220"
Be sure to remove the two preceding ; characters to uncomment these lines.
Lastly, locate the following lines:
cert server.crt
key server.key
We will need to edit these to point to the files that we generated earlier. In our example, we used linuxconfig-server as the common name, so we will change these to:
All set, so save your changes to this file and exit it.
Configure IP Forwarding
On the OpenVPN server, we will need to change the IP forwarding kernel paramater in order to make sure that VPN clients can forward requests to the OpenVPN server, which can then forward them on towards a final destination.
Edit the following file with root permissions:
$ sudo nano /etc/sysctl.conf
At the bottom of the file, add the following line:
net.ipv4.ip_forward = 1
Save your changes and exit the file.
Then, for the changes to take effect, execute:
$ sudo sysctl -p
Start OpenVPN Service
Now that OpenVPN has been configured, we can start the service.
The following command will start the OpenVPN service:
To check the status of the service at any time, use the following command:
$ systemctl status openvpn.service
Create Client Configuration File
The last step is to create a configuration file for your VPN client. This file, along with the .crt files and .key files can then be sent to the VPN clients in order to initiate a connection with the VPN server.
First, copy the client.conf example file to the ~/client-keys directory that we created earlier:
This is only a template file and we will need to make several changes to it. Open the file to begin editing it:
$ nano ~/client-keys/client.conf
Locate the following line:
remote my-server-1 1194
This is where we need to specify the IP of our VPN server. The 1194 is just the port that OpenVPN is running on, so only change this part if necessary. Replace the my-server-1 with the IP address of your OpenVPN server.
Just as we did in the server config file, uncomment the following two lines:
;user nobody
;group nobody
Locate the following lines and comment them out:
ca ca.crt
cert client.crt
key client.key
These will be irrelevant for us, since we are going to use in-line configuration.
Locate the following line and comment it out:
tls-auth ta.key 1
This is an irrelevant line and we will be using an in-line configuration anyway.
This is a bit cumbersome to do, especially at scale, which is why some Bash scripting is recommended if you plan to do this often. At any rate, the final result is a complete linuxconfig-client.ovpn file that can be sent to the OpenVPN client.
Connecting to OpenVPN Server
Connecting to the VPN server is the easiest part. Once you have received all of the files that were generated on the OpenVPN server, use the following command syntax to connect:
$ sudo openvpn --config linuxconfig-client.ovpn
The instructions will of course vary across different operating systems like MacOS and Windows, but essentially the process is nearly the same – just provide the .ovpn file to the OpenVPN client program.
Closing Thoughts
In this tutorial, we saw how to set up an OpenVPN server on a Linux system. This also included the setup of a separate Certificate Authority server using Easy-RSA. The process is quite long, but allows us to self host a VPN server with the best security measures. Now you know how to generate key pairs and configurations for future client connections and can distribute them out in the form of .opvn files.