A Virtual Private Network (VPN) allows you to securely and privately connect to a remote private network, for example, your office network, or the Internet in such a way as if you are directly connected to a private network.
VPN works in a server-client architecture. A VPN server is deployed on a machine and is publicly accessible over the Internet. The VPN server can be configured to allow connecting to a private LAN, such as an office network, or allow connections to the Internet. The user connects to the VPN server using a VPN client on his local machine. Communication between VPN server and client takes place using a secure tunnelling protocol. To the Internet, it seems as if the destination of the traffic is the VPN server; however, the traffic passes to the client via the server.
VPN has many uses in daily life, like securely connecting to a public Wifi network, which is often compromised or bypassing geo-restrictions on certain websites by connecting to a VPN based in a country which is allowed by the website.
OpenVPN is a widely used VPN implementation that allows a wide range of configurations and options. It uses Secure Sockets Layer (SSL) protocol for the encryption of the data and pre-shared keys, username/password or certificates for authentication of the VPN client. In this article, we will see how to set up a VPN server and VPN client on Ubuntu 20.04.
OpenVPN is available in the official Ubuntu repositories in the package
openvpn. This package installs both OpenVPN server as well as the client.
sudo apt install openvpn
As mentioned earlier, OpenVPN uses SSL certificates to encrypt data between the server and the client. We need to set up our own certificate authority (CA) to issue certificates for the VPN. Note that this should be set up on a different machine than the one where OpenVPN is set up; the reason is that if it is on the same server and if it gets compromised, an attacker can access the private key and thus attack the VPN connection.
We will use a tool called ‘Easy-RSA’ to set up the certificate authority. To install it, run the following on the CA machine, the OpenVPN server machine and the client machine, as the configuration is required on all three of these to setup the CA.
sudo apt install easy-rsa
We will now first configure the certificate authority on the CA machine and perform some required configuration steps for the same on the Open VPN server machine.
Certificate Authority Setup
Initial setup on CA machine
Now, this package installs a command called
make-cadir which is used to create a folder for certificate authority configuration. Let’s create a folder using this and enter the folder.
make-cadir cert_authority && cd cert_authority
Open the file called
vars created in this directory. This file contains some configuration variables which we need to modify. The values which need to be modified are on lines 91-96, after the comment about Organizational Fields which describes these fields. Uncomment the lines and fill the appropriate values in place of the sample values.
Save and exit the file. If you are using vim editor, press
:wq and press
Enter to save and exit.
Next, we run the
easyrsa program in the directory to set up the public key infrastructure (PKI), which will be used to generate public key and certificates.
The next step will generate the CA key and certificate. When the command prompts for a password, enter a password for the CA key. Also, enter a common name when prompted. If you leave this blank, the default name Easy-RSA CA name will be used.
As we can see from the output the certificate and key have been generated. This key will be used to sign the client and server certificates, hence it should never be touched/modified.
Now, we have the PKI setup. Next step is to create a server key and certificate on the machine which we will use as an OpenVPN server. This certificate will later be signed by the CA machine.
Generating Server Key and Certificate on the Server machine
We have already installed Easy RSA on the server machine. Now perform the three steps on the server machine, which we previously performed on the CA machine, viz. creating a CA directory using
make-cadir and going inside it, modifying the variables in the
vars file and generating PKI using
./easyrsa init-pki command.
Next, we need to run the command to generate a server certificate request and key.
./easyrsa gen-req server nopass
Note that we passed the option
nopass so that the command will not prompt us to enter a password for the server key. It will still prompt for a common name for the server, which you can enter anything, or leave it empty for the default name (server) to be used.
Move the generated key file inside the
sudo mv pki/private/server.key /etc/openvpn
Send the certificate request to the CA machine. We will use command
scp for this purpose.
scp pki/reqs/server.req user@CA_MACHINE_HOSTNAME:/directory
In the screenshot above, the host 184.108.40.206 is the CA machine. We have copied the certificate in the /root directory.
Now, the certificate of the server has been copied to the CA machine. Next step is to go back to the CA machine and sign this certificate.
Signing the server certificate in the CA
First, let’s verify if the certificate request file from the server has been copied on the CA machine. Go to the directory where we copied the file (/root in my example) and run
:~# cd /root && ls cert_authority server.req
As we can see, the file
server.req is present. Next, go to the CA directory and import this request.
cd cert_authority ./easyrsa import-req /root/server.req server
To sign this request, run the following command.
./easyrsa sign-req server server
Here the first argument is the type of request, i.e., server, and the second argument is the common name of the server machine, for which we previously used the default value, i.e., server.
Enter the phrase yes, and the password for the CA key when prompted.
Now we can remove the certificate request file and copy the generated certificate for the server, as well as CA public certificate back to the server machine.
rm /root/server.req scp pki/issued/server.crt email@example.com:/root scp pki/ca.crt firstname.lastname@example.org:/root
Next, we have to perform few more steps to ensure secure connection of the VPN.
DH Parameters Generation
DH (Diffie-Hellman) key exchange is an algorithm to ensure a secure exchange of crypto keys over an insecure channel. First, let’s move the received certificate and CA public certificate to
mv /root/ca.crt /root/server.crt /etc/openvpn
Go to the CA folder on the server machine and run the following command to generate the DH parameters. It might take a long time to generate.
Now, move the generated file to
mv /root/cert_authority/pki/dh.pem /etc/openvpn
Generating TA keys
OpenVPN uses another additional security measure using TLS auth key. To generate the TLS auth key, run:
openvpn --genkey --secret tls_auth.key
And move the key to
mv tls_auth.key /etc/openvpn
The server key configuration and certificate authority setup is now done. Let us move to the actual configuration of the VPN server now.
OpenVPN Server Configuration
Configuration file for OpenVPN server is not automatically created, however we can use a template configuration file from the
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/ sudo gzip -d /etc/openvpn/server.conf.gz
Open the file using vim or any editor of your choice.
cd /etc/openvpn vim server.conf
We have to enter the common names of keys and certificates that we generated previously. Go to line no. 78. Since we used all the default names, we keep them unchanged. Then check the name for DH parameter file on line 85. We have used the name dh.pem, so let’s change it.
Next, let’s modify the privileges for OpenVPN server. Go to line 274 and 275 and remove the leading
; to uncomment it.
Similarly go to line 192 and remove the semicolon. This directive enables traffic of all the clients to pass through the VPN.
Save and exit the file.
Change the ownership of the folder /etc/openvpn to root.
sudo chown -R root:root /etc/openvpn
Networking and Firewall setup
We need to allow IP forwarding on the server in order to allow packets to be forwarded from and to the VPN client. Uncomment line 28 on
Save and exit the file.
systemctl for these changes to take place.
sudo sysctl -p
We need to set up Network Address Translation (NAT) on the server using a UFW firewall so as to allow the VPN Client access the Internet using the VPN server’s IP Address. First, let’s enable packet forwarding in the firewall configuration. Open
/etc/default/ufw and change the variable on line 19 to ACCEPT.
Save and exit the file.
Now add the following rules to the file
/etc/ufw/before.rules before the filter line in the file.
*nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 10.8.0.0/8 -o <interface> -j MASQUERADE COMMIT
Enter your network interface in place of <interface>. You can see your network interface with the command
Allow traffic for OpenVPN service on the Firewall and allow port 1194.
sudo ufw allow openvpn && sudo ufw allow 1194
Reload the firewall service.
sudo ufw reload
We can now restart the Open VPN server daemon by running:
sudo service openvpn restart
Enable it to start at boot time by running:
sudo systemctl enable openvpn
The OpenVPN server has now been configured and has started. Let’s now proceed to client certificate request and key generation and other configuration.
OpenVPN Client Configuration
We need to generate a key and a certificate request for the client. The procedure to do this is the same as that for the server.
Although a client key and certificate request can be created on the client machine and then transferred to the CA machine, it is recommended to create it on the server machine. The advantage of doing this on the server is that you can create a script for performing all the required steps on the server which makes it easier for a new client to join the VPN.
Go to the CA folder on the server and run the following:
cd ~/cert_authority ./easyrsa gen-req client nopass
In a similar way as done previously, enter a common name when prompted, or leave it empty to use the default common name, i.e., client.
Let’s now copy the generated client certificate request to the CA machine.
scp pki/reqs/client.req email@example.com:/root
Let’s import this request in the CA machine:
./easyrsa import-req /root/client.req client
And let’s now sign it:
./easyrsa sign-req client client
yes when prompted to continue. Enter the password for CA key when asked.
We can now remove the requested file for client and copy the request back to the VPN server machine.
rm /root/client.req scp pki/issued/client.crt firstname.lastname@example.org:/root
Let’s create a folder called
client to keep all files related to the client on the VPN server. We will move the client key and the certificate to this folder.
mkdir ~/client sudo mv ~/client.crt ~/cert_authority/pki/private/client.key ~/client
Now, let’s create a configuration file from an available template, similar to how we created the server configuration file.
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client
Open the file
client.conf. On line 42, enter hostname or IP Address of your server machine in place of
Uncomment lines 61 and 62 by removing the leading semicolon, to downgrade privileges for the file.
Next, comment out lines 88-90 and line 108. The reason is that we want to add the contents of the mentioned files manually instead of using the file locations. The purpose of doing this is that the client configuration file will later be transferred to the client, where we actually won’t have the client key and certificate files; hence we copy contents of those in the configuration file itself.
Append the following to the client configuration file. Enter the file contents of the respective files inside the given tags.
<ca> # Paste content of ca.crt file here </ca> <cert> # Paste content of client.crt file here </cert> <key> # Paste content of client.key file here </key> key-direction 1 <tls-auth> # Paste content of tls_auth.key file here </tls-auth>
Save and exit the file. Rename this file from
client.ovpn, as the latter one is the extension required for configuration files which can be imported as network configurations.
Now, transfer the file
client.ovpn to the client, i.e., local machine.
scp on your client machine to transfer file from server machine to your local machine.
scp user@server_ip:/path_to_file local_destination_path
Finally, we need to use this configuration file to connect to the VPN server. This can be done both via command line as well as GUI.
To start the VPN client from command line, run:
sudo openvpn --config client.ovpn
And that is the only command you need to run to start the VPN Client.
To start the VPN client via GUI, perform the following steps.
Go to Settings » Network on your client machine.
Click on the + button in the VPN section and choose ‘Import from file…’ from the options.
Click on ‘Add’ to start using the VPN.
Note that under ‘Gateway’, it is the IP Address of the server.
Finally, toggle the ‘client VPN’ button to enable VPN on the machine.
It might take a few seconds to establish a VPN connection. A new progress logo for VPN will appear at the top left corner of your screen while it is being set up, and it will change to a VPN logo once it is set up.
To verify if the VPN is working correctly, run the following:
It should return the IP address of your server machine. Or else you can also check your IP address by simply searching ‘My IP’ on Google. It should show your VPN server’s IP address if our VPN setup is working properly.
In this article, we saw how to configure an OpenVPN server, a Certificate Authority and an OpenVPN Client. To add more clients to the VPN, we now need to follow the procedure to generate and sign a certificate for the client and use the same configuration file created here, with only the client key and certificate values changed.
In the case of slower internet connections, it is possible that if UDP is being used for communication, there is considerable packet loss. User can switch to TCP by uncommenting the line
proto tcp and commenting on the line
proto udp in the server configuration file.
Also, in case there are other errors, you can set logging level with the
verb directive in both server and client configuration files. You can enter values between 0 and 9. Higher the value of this directive, more verbose will be the log.