How to Set Up OpenVPN on Ubuntu 20.04
Abstract: $ cp pki/private/my-pc.key /opt/client-configs/keys/ Copy the client certificate request file to the CA servercopy the server key file named openvpn-s
OpenVPN is a feature-rich open-source Secure Socket Layer (SSL) VPN. VPN allows to securely connect untrusted networks such as WIFI network in hotels or airports or malls. VPN also allows a secure connection to the corporate network to access resources. The tunnels are secured by using SSL/TLS authentication, certificates, credentials.
In this tutorial, I will show you how to setup a VPN using OpenVPN on Ubuntu 20.04.
Pre requisitesWe will use two Ubuntu servers running on version 20.04:
Own Unlimited Free VPN Server Setup...To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
Own Unlimited Free VPN Server Setup Ubuntu on Free VPS | SSH | SSL TLS | Squid Proxy | OpenVPN- A Certificate Authority (CA) server that will validate the request and sign the certificates of the clients.
- The OpenVPN server on which we will install the VPN.
It recommended keeping a standalone server to serve as your CA (certificate authority). This is because of security reasons. Let's proceed to configure the CA server.
First make sure system is updated. Run the following the command:
$ sudo apt update
You will need to create a non root user for the configurations of the Certificate Authority server.
$ sudo adduser malain
Now give to the user the sudo privileges:
$ sudo usermod -aG sudo malain
Now logout and then login back with the non-root user.
Install EasyRSA on CA serverEasy-rsa is a CLI utility to build and manage a PKI CA. Easy-RSA will be used by the CA server to generate a private key and public root certificate which will be used to sign the requests from clients and servers that will rely on our CA.
To install easy-rsa, download the PKI management tool from github using wget:
$ wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
Then uncompress tgz file:
$ tar xvf EasyRSA-3.0.8.tgz
To restrict the access to the user only, use:
$ chmod 700 EasyRSA-3.0.8
Now move EasyRSA to the opt
directory
$ sudo mv EasyRSA-3.0.8 /opt/
We are using EasyRSA 3.0.8 version for this configuration.
Create CA using EasyRSAFirst, you need to create a file named vars
to store the organization information. For this, we can use the example file available in EasyRSA-3.0.8 directory.
To list files under EasyRSA directory, use:
$ cd EasyRSA-3.0.8/ && ls -l
Output:
-rw-rw-r-- 1 malain malain 1305 Sep 9 2020 COPYING.md
-rw-rw-r-- 1 malain malain 5056 Sep 9 2020 ChangeLog
-rw-rw-r-- 1 malain malain 2049 Sep 9 2020 README.md
-rw-rw-r-- 1 malain malain 3335 Sep 9 2020 README.quickstart.md
drwxrwxr-x 2 malain malain 4096 Sep 9 2020 doc
-rwxrwxr-x 1 malain malain 76946 Sep 9 2020 easyrsa
-rw-rw-r-- 1 malain malain 18093 Sep 9 2020 gpl-2.0.txt
-rw-rw-r-- 1 malain malain 1036 Sep 9 2020 mktemp.txt
-rw-rw-r-- 1 malain malain 4616 Sep 9 2020 openssl-easyrsa.cnf
-rw-rw-r-- 1 malain malain 8925 Sep 9 2020 vars.example
drwxrwxr-x 2 malain malain 4096 Mar 28 14:14 x509-types
Make a copy of the file vars.example as vars:
$ cp vars.example vars
Now open vars file and adding the organization information at the end of the file:
$ vim vars
set_var EASYRSA_REQ_COUNTRY "CM"
set_var EASYRSA_REQ_PROVINCE "Littoral"
set_var EASYRSA_REQ_CITY "Douala"
set_var EASYRSA_REQ_ORG "OPEN-SHARE"
set_var EASYRSA_REQ_EMAIL "[email protected]"
set_var EASYRSA_REQ_OU "Com"
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"
Now initialize our PKI on our CA server which will create the pki folder.
$ ./easyrsa init-pki
We can now generate the root public and private key pair for our CA. During the process, normally you will be asked to enter a passphrase for the key pair anytime that you will need to sign or revoke a certificate. In our case, we will use the command so that we will be not prompted for a passphrase. You will also be prompted to indicate a Common Name (CN) but we will leave the default one by pressing Enter key.
$ ./easyrsa build-ca nopass
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
read EC key
writing EC key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/opt/EasyRSA-3.0.8/pki/ca.crt
This will create root certificate named ca.crt file in the pki directory and the private key ca.key in the pki/private directory.
$ ls -l pki/
total 52
-rw------- 1 malain malain 749 Mar 28 14:30 ca.crt
drwx------ 2 malain malain 4096 Mar 28 14:29 certs_by_serial
drwx------ 2 malain malain 4096 Mar 28 14:29 ecparams
-rw------- 1 malain malain 0 Mar 28 14:29 index.txt
-rw------- 1 malain malain 0 Mar 28 14:29 index.txt.attr
drwx------ 2 malain malain 4096 Mar 28 14:29 issued
-rw------- 1 malain malain 4616 Mar 28 14:24 openssl-easyrsa.cnf
drwx------ 2 malain malain 4096 Mar 28 14:30 private
drwx------ 5 malain malain 4096 Mar 28 14:29 renewed
drwx------ 2 malain malain 4096 Mar 28 14:24 reqs
drwx------ 5 malain malain 4096 Mar 28 14:29 revoked
-rw------- 1 malain malain 4575 Mar 28 14:24 safessl-easyrsa.cnf
-rw------- 1 malain malain 3 Mar 28 14:29 serial
$ ls -l pki/private/
total 4
-rw------- 1 malain malain 288 Mar 28 14:29 ca.key
With this, our CA server is ready.
Install and Configure Openvpn ServerLets jump on to the second server to install and configure openvpn. You will also need to create a non-root user in this server and give him the sudo
privileges.
To install openvpn on ubuntu, run the following commands:
$ sudo apt update
$ sudo apt install openvpn
On the openvpn server, easyrsa will be used to generate a certificate request that will be verified and signed by the CA Server. Follow the same steps we followed in the last section to install Easyrsa.
$ wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
Now uncompress the downloaded tgz file:
$ tar xvf EasyRSA-3.0.8.tgz
Restrict the access to the user only:
$ chmod 700 EasyRSA-3.0.8
Move EasyRSA-3.0.8 to the opt
directory:
$ sudo mv EasyRSA-3.0.8 /opt/
Create a PKI
Now we need to create PKI that will help to request and manage TLS certificates for the clients and the other servers that will connect to our VPN.
Lets create a vars file using the already available examples file:
$ cp vars.example vars
Now edit vars file by adding the following lines at the end of the file:
$ vim vars
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"
To create the PKI folder on the openvpn server, run the easyrsa
script file:
$ ./easyrsa init-pki
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /opt/EasyRSA-3.0.8/pkiCreate the server certificate request and the private key
Now we will generate a private key and certificate request on the OpenVPN server. Then we will transfer the certificate request file to the CA server to be signed in order to create the required certificate
Being in the same folder, we can generate the request with the nopass
option. The following command creates a private key file named openvpn-server.key and a certificate request file named openvpn-server.req.
$ ./easyrsa gen-req openvpn-server nopass
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
Generating an EC private key
writing new private key to '/opt/EasyRSA-3.0.8/pki/easy-rsa-4737.CGhQHN/tmp.UGQ9wi'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [openvpn-server]:
Keypair and certificate request completed. Your files are:
req: /opt/EasyRSA-3.0.8/pki/reqs/openvpn-server.req
key: /opt/EasyRSA-3.0.8/pki/private/openvpn-server.key
Now, copy the server key file named openvpn-server.key to the directory named /etc/openvpn/server.
$ sudo cp /opt/EasyRSA-3.0.8/pki/private/openvpn-server.key /etc/openvpn/server
Then copy certificate request file to the CA server:
$ scp /opt/EasyRSA-3.0.8/pki/reqs/openvpn-server.req [email protected]:/tmp
On the CA server, change to the easyrsa directory,
$ cd /opt/EasyRSA-3.0.8/
To import the request, run the following command:
$ ./easyrsa import-req /tmp/openvpn-server.req openvpn-server
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
The request has been successfully imported with a short name of: openvpn-server
You may now use this name to perform signing operations on this request.
Now sign the request. As we are signing the request of the server, we should use the directive server
before the Common Name of our openvpn server. If it was a request of a client, we should be using the directive client
instead.
To sign the request:
$ ./easyrsa sign-req server openvpn-server
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a server certificate for 825 days:
subject=
commonName = openvpn-server
Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /opt/EasyRSA-3.0.8/pki/easy-rsa-4100.IbygpP/tmp.hJY2T5
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'openvpn-server'
Certificate is to be certified until Jul 1 19:50:36 2023 GMT (825 days)
Write out database with 1 new entries
Data Base Updated
Certificate created at: /opt/EasyRSA-3.0.8/pki/issued/openvpn-server.crt
Now the OpenVPN server’s certificate request has been signed by the CA server, we need to transfer the signed request and the public certificate to the OpenVPN server.
$ scp pki/{ca.crt,issued/openvpn-server.crt} [email protected]:/tmp
$ sudo cp /tmp/{ca.crt,openvpn-server.crt} /etc/openvpn/server
We will now generate the tls-crypt pre-shared key to ensure that our OpenVPN server is able to cope with unauthenticated traffic, port scans, and some attacks which can use a lot of the server's resources.
$ ./easyrsa gen-dh
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020 Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time ....................................+.......................... ............................................................... ............................................................... ...........................................+.......+.......+... .....+.......................................................... ...............................++*++*++*++* DH parameters of size 2048 created at /opt/EasyRSA-3.0.8/pki/dh.pem
$ openvpn --genkey --secret ta.key
Now copy the key and pem files to the directory /etc/openvpn/server:
$ sudo cp ta.key pki/dh.pem /etc/openvpn/server
Generate a client certificate and key pair
We will need to create a directory to keep the certificates and the keys of the clients. Make sure to give permission to the non-root user.
$ sudo mkdir -p /opt/client-configs/keys
$ sudo chown franck:franck -R /opt/client-configs
$ sudo chmod 700 -R /opt/client-configs
Generate the request for the client certificate:
$ cd /opt/EasyRSA-3.0.8
$ ./easyrsa gen-req my-pc nopass
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020 Generating an EC private key writing new private key to '/opt/EasyRSA-3.0.8/pki/easy-rsa-6961.m7fBMu/tmp.dkqaZI' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Common Name (eg: your user, host, or server name) [my-pc]: Keypair and certificate request completed. Your files are: req: /opt/EasyRSA-3.0.8/pki/reqs/my-pc.req key: /opt/EasyRSA-3.0.8/pki/private/my-pc.key
Now copy the client key to the client-configs directory:
$ cp pki/private/my-pc.key /opt/client-configs/keys/
Copy the client certificate request file to the CA server:
$ scp pki/reqs/my-pc.req [email protected]:/tmp
On the CA server, import the CSR:
$ cd /opt/EasyRSA-3.0.8
$ ./easyrsa import-req /tmp/my-pc.req my-pc
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
The request has been successfully imported with a short name of: my-pc
You may now use this name to perform signing operations on this request.
Now we should sign the request for client, type:
$ ./easyrsa sign-req client my-pc
Output:
Note: using Easy-RSA configuration from: /opt/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.1.1f 31 Mar 2020
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a client certificate for 825 days:
subject=
commonName = my-pc
Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /opt/EasyRSA-3.0.8/pki/easy-rsa-5511.IwDcbS/tmp.doUbCv
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'my-pc'
Certificate is to be certified until Jul 1 21:33:52 2023 GMT (825 days)
Write out database with 1 new entries
Data Base Updated
Certificate created at: /opt/EasyRSA-3.0.8/pki/issued/my-pc.crt
Copy the client certificate on the openvpn server:
$ scp pki/issued/my-pc.crt [email protected]:/tmp
Now on the openvpn server, we need to copy all the client files to the client directory that we have created before.
$ sudo cp /tmp/my-pc.crt /opt/client-configs/keys/
$ sudo cp /etc/openvpn/server/ca.crt /opt/client-configs/keys/
$ cp /opt/EasyRSA-3.0.8/ta.key /opt/client-configs/keys/
Make sure that the non-root user has the permissions on the files.
$ sudo chown franck:franck /opt/client-configs/keys/*
Configure VPN service
We should first make a copy of the template to use
$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/server/
Then uncompress the file
$ sudo gzip -d /etc/openvpn/server/server.conf.gz
And enter to the folder
$ cd /etc/openvpn/server
Some lines will be replaced to match our configuration::
- The cryptographic ciphers will be set to
AES-256-CBC
- The HMAC message digest algorithm will be
sha256
- As we also use a Diffie-Hellman parameter, we will set it to
dh.pem
- We will use the user nobody and group nogroup to run openvpn with no privileges once it has started
- We will push the dns changes to redirect all traffic through the vpn with the values
push redirect-gateway def1 bypass-dhcp
,push dhcp-option DNS 208.67.222.222
,push dhcp-option DNS 208.67.220.220
- We will keep the default port
1194
- We will use the
udp
protocol - we should indicate the key
openvpn-server.key
and certificateopenvpn-server.crt
to use as the credential
So the file should look as below:
$ sudo vim /etc/openvpn/server/server.conf
tls-crypt ta.key
cipher AES-256-CBC
auth SHA256
dh dh.pem
user nobody
group nogroup
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
port 1194
proto udp
explicit-exit-notify 1
cert openvpn-server.crt
key openvpn-server.key
You should activate the ip forwarding by editing net.ipv4.ip_forward value in /etc/sysctl.conf.
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_forward=1
To make the changes we made in /etc/sysctl.conf effective, run:
$ sudo sysctl -p
net.ipv4.ip_forward = 1
Now you need to allow OpenVPN through your firewall by enabling the masquerading. To do that, you need to identify the name of your public network interface:
$ ip route | grep default
default via X.X.X.X dev eth0 proto static
In our case it's eth0. Now we should add the masquerades rules in the firewall configuration, so we will add the line below at the top of the rules' files:
$ sudo vim /etc/ufw/before.rules
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to the public server interface eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES
Now let's edit ufw to allow forwarded packets by default.
$ sudo vim /etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
Open the openvpn port on the firewall:
$ sudo ufw allow '1194/udp'
To restart ufw service, type:
$ sudo ufw disable && sudo ufw enable
To enable the openvpn service to start as the system startup, type:
$ sudo systemctl enable openvpn-server@server
To start openvpn, type:
$ sudo systemctl start openvpn-server@server
You can check openvpn status by:
$ sudo systemctl status openvpn-server@server
Output:
● [email protected] - OpenVPN service for server
Loaded: loaded (/lib/systemd/system/[email protected]; disabled; vendor preset: enabled)
Active: active (running) since Sun 2021-03-28 23:30:57 UTC; 8s ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 78132 (openvpn)
Status: "Initialization Sequence Completed"
Tasks: 1 (limit: 1073)
Memory: 1.0M
CGroup: /system.slice/system-openvpn\x2dserver.slice/[email protected]
└─78132 /usr/sbin/openvpn --status /run/openvpn-server/status-server.log --status-version 2 --suppress-timestamps --config server.conf
Mar 28 23:30:57 localhost systemd[1]: Starting OpenVPN service for server...
Mar 28 23:30:57 localhost systemd[1]: Started OpenVPN service for server.
To check the tunnel interface, type:
$ ip addr show tun0
Output:
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::c3d9:85d1:e2a9:6b2c/64 scope link stable-privacy
valid_lft forever preferred_lft forever
Configure vpn files for clients
$ sudo mkdir -p /opt/client-configs/files
Now we should copy the sample configuration file
$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /opt/client-configs/base.conf
Give the permission to the non root user
$ sudo chown franck:franck -R /opt/client-configs/
Edit the base.conf file
$ vim /opt/client-configs/base.conf
remote your_server_ip 1194
proto udp
# Downgrade privileges after initialization (non-Windows only)
user nobody
group nogroup
#ca ca.crt
#cert client.crt
#key client.key
#tls-auth ta.key 1
cipher AES-256-CBC
auth SHA256
key-direction 1
# For the clients using resolvconf for DNS resolution, uncomment the lines below on the client computer
; script-security 2
; up /etc/openvpn/update-resolv-conf
; down /etc/openvpn/update-resolv-conf
# Instead for the clients using systemd-resolved for DNS resolution, uncomment the lines below on the client computer
; script-security 2
; up /etc/openvpn/update-systemd-resolved
; down /etc/openvpn/update-systemd-resolved
; down-pre
; dhcp-option DOMAIN-ROUTE .
Now we will create a script to generate the certificates and encrypted files on the client. The script will also make a copy of the base.conf file and collect all the keys and certificates created for the clients. For each client, we would need to generate a certificate and key before running the script
$ vim /opt/client-configs/make_config.sh
#!/bin/bash
# First argument: Client identifier
KEY_DIR=/opt/client-configs/keys
OUTPUT_DIR=/opt/client-configs/files
BASE_CONFIG=/opt/client-configs/base.conf
cat ${BASE_CONFIG} \
<(echo -e '<ca>') \
${KEY_DIR}/ca.crt \
<(echo -e '</ca>\n<cert>') \
${KEY_DIR}/${1}.crt \
<(echo -e '</cert>\n<key>') \
${KEY_DIR}/${1}.key \
<(echo -e '</key>\n<tls-auth>') \
${KEY_DIR}/ta.key \
<(echo -e '</tls-auth>') \
> ${OUTPUT_DIR}/${1}.ovpn
Make sure that only the non-root user can run the script.
$ chmod 700 /opt/client-configs/make_config.sh
Now you can generate the client connection file based on the client key and certificate configuration (my-pc.crt and my-pc.key)
$ cd /opt/client-configs
Now run the script followed by the common name used for the client which will create the client vpn file to use.
$ ./make_config.sh my-pc
You can check the result:
$ ls -l files/
total 12
-rw-rw-r-- 1 franck franck 8598 Mar 30 11:12 my-pc.ovpn
Connect client to the OpenVPN connection
Install openvpn on the client. This will be use to establish the vpn connection with the server
$ sudo apt update && sudo apt install openvpn -y
Now copy the OpenVPN client file which is on the server to your client computer. So, on your client computer do the following command:
$ rsync -av [email protected]:/opt/client-configs/files/my-pc.ovpn .
Before editing the client OpenVPN configuration file, we must check if we use resolvconf or systemd-resolved for DNS resolution
$ cat /etc/resolv.conf
OUTPUT:
# This file is managed by man:systemd-resolved(8). Do not edit.
. . .
nameserver 127.0.0.53
options edns0
With the value nameserver 127.0.0.53
, it shows that you use systemd-resolved. So, install a package which will help systemd-resolved to use the VPN for the DNS resolution when connected.
$ sudo apt install openvpn-systemd-resolved
Now we can edit the vpn client file by uncommenting the lines needed for systemd-resolved
$ vim my-pc.ovpn
script-security 2
up /etc/openvpn/update-systemd-resolved
down /etc/openvpn/update-systemd-resolved
down-pre
dhcp-option DOMAIN-ROUTE .
For the system using update-resolv-conf, you will uncomment the lines
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf
Now let's try connecting to the VPN using openvpn command to the client configuration file:
$ sudo openvpn --config my-pc.ovpn
You can check the ip information for the tunnel interface
$ ip a
This will show a tunnel ip address and we can make a ping to the OpenVPN server. With this, you can confirm that you are able to reach your server as if you were in the same private network.
ConclusionIt's easy to set up a VPN connection when using OpenVPN. This is a good solution when you want to set up a VPN solution on your cloud server without using any specialized solution such as a virtual firewall or anything else. It's a fast and secure solution.