OpenVPN is an open-source VPN solution for businesses that use virtual private network techniques to create secure point-to-point connections with remote access facilities. OpenVPN is a trusted technology used by many VPNs to make sure any data sent over the internet is encrypted and private.

In simple terms, OpenVPN allows you to connect to other devices within one secure network. It is cross-platform and can be Windows, Mac, Android, iOS, and Linux. OpenVPN offers a rich set of features including:

  • Unlimited Bandwidth
  • Unlimited Server Switches
  • Multi-Device Usage
  • No Log Storage
  • Protocol Choices
  • Multiple Concurrent Connections

In this tutorial, we will learn how to install and configure the OpenVPN server and client on an Ubuntu 20.04 VPS.

Step 1: Enable IP Forwarding

First, you will need to enable IP forwarding in your system so that OpenVPN can correctly route traffic through the VPN.

You can enable IP forwarding by editing the file /etc/sysctl.conf:

nano /etc/sysctl.conf

Uncomment the following line:

net.ipv4.ip_forward = 1

Save the file when you are finished, then run the following command to apply the changes:

sysctl -p

Step 2: Install OpenVPN Server

By default, the OpenVPN package is available in Ubuntu 20.04, so you can install it by just running the following command:

apt-get install openvpn -y

Once the installation has been completed, you can proceed to the next step.

Step 3: Build the Certificate Authority

To set up the certificate authority and PKI infrastructure, you will need to download EasyRSA in your system. You can download it with the following command:

wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.6/EasyRSA-unix-v3.0.6.tgz

Once downloaded, extract the downloaded file with the following command:

tar -xvzf EasyRSA-unix-v3.0.6.tgz

Next, move the extracted directory to the /etc/openvpn/ with the following command:

mv EasyRSA-v3.0.6 /etc/openvpn/easy-rsa

Next, change the directory to /etc/openvpn/easy-rsa and create a EasyRSA configuration file:

cd /etc/openvpn/easy-rsa
nano vars

Add the following lines including your country, city, and preferred email address:

set_var EASYRSA                 "$PWD"
set_var EASYRSA_PKI             "$EASYRSA/pki"
set_var EASYRSA_DN              "cn_only"
set_var EASYRSA_REQ_COUNTRY     "INDIA"
set_var EASYRSA_REQ_PROVINCE    "Gujarat"
set_var EASYRSA_REQ_CITY        "Junagadh"
set_var EASYRSA_REQ_ORG         "Atlantic CERTIFICATE AUTHORITY"
set_var EASYRSA_REQ_EMAIL     "[email protected]"
set_var EASYRSA_REQ_OU          "Atlantic EASY CA"
set_var EASYRSA_KEY_SIZE        2048
set_var EASYRSA_ALGO            rsa
set_var EASYRSA_CA_EXPIRE      7500
set_var EASYRSA_CERT_EXPIRE     365
set_var EASYRSA_NS_SUPPORT  "no"
set_var EASYRSA_NS_COMMENT            "Atlantic CERTIFICATE AUTHORITY"
set_var EASYRSA_EXT_DIR         "$EASYRSA/x509-types"
set_var EASYRSA_SSL_CONF        "$EASYRSA/openssl-easyrsa.cnf"
set_var EASYRSA_DIGEST          "sha256"

Save the file when you are finished.

Next, initiate the PKI directory using the following command:

./easyrsa init-pki

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/easy-rsa/pki

Next, build the CA certificates with the following command:

./easyrsa build-ca

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020

Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................................................................................+++++
..................................................+++++
e is 65537 (0x010001)
Can't load /etc/openvpn/easy-rsa/pki/.rnd into RNG
139636302492992:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:98:Filename=/etc/openvpn/easy-rsa/pki/.rnd
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:
/etc/openvpn/easy-rsa/pki/ca.crt

The above command will generate two files named ca.key and ca.crt. These certificates will be used to sign your server and clients’ certificates.

Step 4: Create Server Certificate Files

Next, you will need to generate a keypair and certificate request for your server.

Run the following command to generate the server key named atlantic-server:

./easyrsa gen-req atlantic-server nopass

You should see the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020
Generating a RSA private key
.............................+++++
...+++++
writing new private key to '/etc/openvpn/easy-rsa/pki/private/atlantic-server.key.IMonKybM0y'
-----
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) [atlantic-server]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/pki/reqs/atlantic-server.req
key: /etc/openvpn/easy-rsa/pki/private/atlantic-server.key

This will generate a private key and a certificate request file for the server.

Step 5: Sign the Server Key Using CA

Next, you will need to sign the atlantic-server key using your CA certificate:

You can sign the server key using the following command:

./easyrsa sign-req server atlantic-server

You should see the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020

You are about to sign the following certi
ficate.
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 365 days:

subject=
commonName                = atlantic-server

Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'atlantic-server'
Certificate is to be certified until Jun 29 11:43:05 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /etc/openvpn/easy-rsa/pki/issued/atlantic-server.crt

Next, verify the generated certificate file with the following command:

openssl verify -CAfile pki/ca.crt pki/issued/atlantic-server.crt

You should get the following output:

pki/issued/atlantic-server.crt: OK

Next, run the following command to generate a strong Diffie-Hellman key to use for the key exchange:

./easyrsa gen-dh

You should get the following output:

Note: using Easy-RSA configuration from: ./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 /etc/openvpn/easy-rsa/pki/dh.pem

After creating all certificate files, copy them to the /etc/openvpn/server/ directory:

cp pki/ca.crt /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp pki/private/atlantic-server.key /etc/openvpn/server/
cp pki/issued/atlantic-server.crt /etc/openvpn/server/

Step 6: Generate Client Certificate and Key File

Next, you will need to create the key and certificate file for the client.

First, run the following command to build the client key file:

./easyrsa gen-req client nopass

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020
Generating a RSA private key
...+++++
........+++++
writing new private key to '/etc/openvpn/easy-rsa/pki/private/client.key.JmBal6cmr8'
-----
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) [client]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/pki/reqs/client.req
key: /etc/openvpn/easy-rsa/pki/private/client.key

Next, sign the client key using your CA certificate:

./easyrsa sign-req client client

You should get the following output:

Note: using Easy-RSA configuration from: ./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 365 days:

subject=
commonName                = client

Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'client'
Certificate is to be certified until Jun 29 11:46:58 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /etc/openvpn/easy-rsa/pki/issued/client.crt

Next, copy all client certificates and key files to the /etc/openvpn/client/ directory:

cp pki/ca.crt /etc/openvpn/client/
cp pki/issued/client.crt /etc/openvpn/client/
cp pki/private/client.key /etc/openvpn/client/

Step 7: Configure OpenVPN Server

At this point, all certificates and key files are ready. Next, create a new OpenVPN configuration file inside /etc/openvpn/ directory:

nano /etc/openvpn/server.conf

Add the following lines per your certificate and key path:

port 1194
proto udp
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/atlantic-server.crt
key /etc/openvpn/server/atlantic-server.key
dh /etc/openvpn/server/dh.pem
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1"

push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
duplicate-cn
cipher AES-256-CBC
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-
CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-
CBC-SHA256
auth SHA512
auth-nocache
keepalive 20 60
persist-key
persist-tun
compress lz4
daemon
user nobody
group nogroup
log-append /var/log/openvpn.log
verb 3

Save the file when you are finished, then start the OpenVPN service and enable it to start after the system reboot using the following command:

systemctl start openvpn@server
systemctl enable openvpn@server

Run the following command to verify the status of OpenVPN service:

systemctl status openvpn@server

You should get the following output:

Loaded: loaded (/lib/systemd/system/[email protected]; disabled; vendor preset: enabled)
Active: active (running) since Mon 2020-06-29 11:48:25 UTC; 7s ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 2868 (openvpn)
Status: "Initialization Sequence Completed"
Tasks: 1 (limit: 2353)
Memory: 2.0M
CGroup: /system.slice/system-openvpn.slice/[email protected]
└─2868 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --script-security 2 --conf>

Jun 29 11:48:25 vpnserver systemd[1]: Starting OpenVPN connection to server...
Jun 29 11:48:25 vpnserver systemd[1]: Started OpenVPN connection to server.

Once the OpenVPN service has started successfully, it will create a new network interface named tun0. You can verify it with the following command:

ip a show tun0

You should get the new interface tun0 in the following output:

4: 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::5f83:99a:30d:eb0/64 scope link stable-privacy
valid_lft forever preferred_lft forever

Step 8: Create Client Configuration File

Next, you will need to create an OpenVPN client configuration file named client.ovpn. You will need this file to connect your OpenVPN server from the client system.

nano /etc/openvpn/client/client.ovpn

Add the following lines:

client
dev tun
proto udp
remote your-vpn-server-ip 1194
ca ca.crt
cert client.crt
key client.key
cipher AES-256-CBC
auth SHA512
auth-nocache
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-
CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-
CBC-SHA256
resolv-retry infinite
compress lz4
nobind
persist-key
persist-tun
mute-replay-warnings
verb 3

Save the file when you are finished.

Step 9: Install and Configure OpenVPN Client

Next, you will need to install OpenVPN on the client system and connect to the OpenVPN server.

First, log in to the client machine and install the OpenVPN package with the following command:

apt-get install openvpn -y

Next, you will need to copy the OpenVPN client configuration files from the OpenVPN server to the client machine.

On the client machine, run the following command to download all the client configuration files:

scp -r root@vpn-server-ip:/etc/openvpn/client .

Once all files are copied, change the directory to the client and run the following command to connect to the OpenVPN server:

cd client
openvpn --config client.ovpn

Once you are connected to the OpenVPN server, you should see the following output:

Jun 29 11:48:27 2020 TCP/UDP: Preserving recently used remote address: 
[AF_INET]69.87.218.145:1194
Jun 29 11:48:27 2020 Socket Buffers: R=[212992->212992] S=[212992->212992]
Jun 29 11:48:27 2020 UDP link local: (not bound)
Jun 29 11:48:27 2020 UDP link remote: [AF_INET]69.87.218.145:1194
Jun 29 11:48:27 2020 TLS: Initial packet from [AF_INET]69.87.218.145:1194, sid=6d27e1cb 
524bd8cd
Jun 29 11:48:27 2020 VERIFY OK: depth=1, CN=Easy-RSA CA
Jun 29 11:48:27 2020 VERIFY OK: depth=0, CN=atlantic-server
Jun 29 11:48:27 2020 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 
2048 bit RSA
Jun 29 11:48:27 2020 [atlantic-server] Peer Connection Initiated with 
[AF_INET]69.87.218.145:1194
Jun 29 11:48:27 2020 SENT CONTROL [atlantic-server]: 'PUSH_REQUEST' (status=1)
Jun 29 11:48:27 2020 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway 
def1,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,route 10.8.0.1,topology 
net30,ping 20,ping-restart 60,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
Jun 29 11:48:27 2020 OPTIONS IMPORT: timers and/or timeouts modified
Jun 29 11:48:27 2020 OPTIONS IMPORT: --ifconfig/up options modified
Jun 29 11:48:27 2020 OPTIONS IMPORT: route options modified

After a successful connection, OpenVPN will assign an IP address to your system. You can check it with the following command:

ip a show tun0

Output:

4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state 
UNKNOWN group default qlen 100
link/none
inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::7226:57b1:f101:313b/64 scope link stable-privacy
valid_lft forever preferred_lft forever

You can also check the OpenVPN server log to verify the connection status using the following command:

tail -f /var/log/openvpn.log

Conclusion

Congratulations! You have successfully set up a VPN server with OpenVPN on an Ubuntu 20.04 VPS. You can now access the internet securely and protect your identity, location, and traffic. Visit the OpenVPN official documentation for more information.