Establishing a Virtual Private Network (VPN) offers a secure and private way to connect to a remote network over the internet, making it appear as though you're directly connected to a private network. This is particularly useful for accessing office networks remotely or protecting your data on public Wi-Fi networks. In this guide, we'll walk through setting up an OpenVPN server on Ubuntu 20.04, covering everything from installing the necessary packages to configuring both the server and client.

Installation

To begin, you'll need to install the OpenVPN package available in Ubuntu's official repositories. This package includes both the server and client components.

sudo apt install openvpn

OpenVPN uses SSL certificates to encrypt data between the server and clients. To manage these certificates, we'll set up our own Certificate Authority (CA). For security reasons, it's recommended to set up the CA on a separate machine from the OpenVPN server; this way, if the server is compromised, the CA's private key remains secure.

We'll use the 'Easy-RSA' tool to handle certificate generation and management. Install Easy-RSA on the CA machine, the OpenVPN server machine, and the client machine, as we'll need to perform configurations on all three.

sudo apt install easy-rsa

Now, let's configure the Certificate Authority on the CA machine and prepare the OpenVPN server accordingly.

Certificate Authority setup

Initial setup on CA machine

Step 1: Create a directory for the Certificate Authority using the make-cadir command and navigate into it.

make-cadir cert_authority && cd cert_authority

Open the vars file in this directory. Uncomment lines 91-96, which contain configuration variables for organizational fields, and replace the sample values with your own information.

Save and exit the file. If you're using vim, press Esc, type :wq, and press Enter.

Step 2: Initialize the Public Key Infrastructure (PKI) by running:

./easyrsa init-pki

Step 3: Build the Certificate Authority. You'll be prompted to set a password for the CA key and enter a common name (you can leave it blank to use the default).

./easyrsa build-ca

The CA key and certificate are now generated. Keep the CA key secure, as it's used to sign server and client certificates.

Generating server key and certificate on the server machine

On the server machine, perform similar initial steps for Easy-RSA.

Step 1: Create the Easy-RSA directory and navigate into it:

make-cadir cert_authority && cd cert_authority

Edit the vars file, updating the organizational fields as you did on the CA machine. Initialize the PKI:

./easyrsa init-pki

Step 2: Generate the server's private key and certificate request. The nopass option allows OpenVPN to start without a password prompt.

./easyrsa gen-req server nopass

When prompted for a common name, you can leave it blank to use 'server' by default.

Step 3: Move the generated server key to the /etc/openvpn directory.

sudo mv pki/private/server.key /etc/openvpn

Step 4: Transfer the server certificate request to the CA machine using scp (secure copy).

scp pki/reqs/server.req user@CA_MACHINE_IP:/root

Replace user and CA_MACHINE_IP with your CA machine's username and IP address.

Signing the server certificate on the CA machine

On the CA machine, ensure the server's certificate request has been received.

Step 1: Import the server's certificate request into Easy-RSA.

cd cert_authority
./easyrsa import-req /root/server.req server

Step 2: Sign the server's certificate request. Type yes when prompted and enter the CA key password.

./easyrsa sign-req server server

Step 3: Clean up by removing the server request file and transferring the signed certificate and CA certificate back to the server machine.

rm /root/server.req
scp pki/issued/server.crt root@SERVER_IP:/root
scp pki/ca.crt root@SERVER_IP:/root

Replace SERVER_IP with your server's IP address.

Generating DH parameters

On the server machine, move the certificates to the OpenVPN directory.

Step 1: Move the certificates:

sudo mv /root/server.crt /root/ca.crt /etc/openvpn

Step 2: Generate the Diffie-Hellman (DH) parameters (this may take some time):

cd cert_authority
./easyrsa gen-dh

Step 3: Move the generated dh.pem file to /etc/openvpn.

sudo mv pki/dh.pem /etc/openvpn

Generating TLS authentication key

Step 4: Generate the TLS authentication key:

openvpn --genkey --secret tls_auth.key

Step 5: Move the key to the OpenVPN directory:

sudo mv tls_auth.key /etc/openvpn

With these steps, the server's key configuration and Certificate Authority setup are complete.

OpenVPN server configuration

Next, we'll configure the OpenVPN server using a sample configuration file provided by the OpenVPN package.

Step 1: Copy the sample server configuration file to /etc/openvpn and decompress it:

sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
sudo gzip -d /etc/openvpn/server.conf.gz

Step 2: Edit the server configuration file:

sudo vim /etc/openvpn/server.conf

Update the paths to match your key and certificate files. Since we used the default names, lines 78 can remain unchanged. On line 85, change the dh parameter file name to dh.pem to match the file we generated.

Uncomment lines 192, 274, and 275 by removing the leading semicolons to adjust server privileges and enable client traffic routing.

Save and exit the file.

Step 3: Change the ownership of the OpenVPN directory to root:

sudo chown -R root:root /etc/openvpn

Networking and firewall setup

Step 4: Enable IP forwarding by editing /etc/sysctl.conf. Uncomment the line net.ipv4.ip_forward=1 by removing the leading #.

Save and exit the file, then apply the changes:

sudo sysctl -p

Step 5: Adjust UFW settings by editing /etc/default/ufw. Change DEFAULT_FORWARD_POLICY from DROP to ACCEPT.

Save and exit the file.

Step 6: Add the following rules to /etc/ufw/before.rules before the *filter line to allow NAT:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/8 -o <interface> -j MASQUERADE
COMMIT

Replace <interface> with your network interface name (use ifconfig to find it).

Step 7: Allow OpenVPN through the firewall and open port 1194:

sudo ufw allow openvpn
sudo ufw allow 1194

Reload UFW to apply the changes:

sudo ufw reload

Step 8: Restart the OpenVPN service and enable it to start on boot:

sudo systemctl restart openvpn
sudo systemctl enable openvpn

The OpenVPN server is now configured and running.

OpenVPN client configuration

To allow a client to connect, we'll generate a key and certificate for the client on the server machine.

Step 1: On the server, navigate to the Easy-RSA directory and generate the client request (replace client1 with a unique identifier for your client):

cd cert_authority
./easyrsa gen-req client1 nopass

When prompted for a common name, you can use the default or enter a unique one.

Step 2: Transfer the client certificate request to the CA machine:

scp pki/reqs/client1.req root@CA_MACHINE_IP:/root

Step 3: On the CA machine, import and sign the client's certificate request:

cd cert_authority
./easyrsa import-req /root/client1.req client1
./easyrsa sign-req client client1

Type yes when prompted and enter the CA key password.

Step 4: Transfer the signed client certificate back to the server:

scp pki/issued/client1.crt root@SERVER_IP:/root
rm /root/client1.req

Step 5: Create a directory on the server to store client files and move the client key and certificate there:

mkdir ~/client-configs
sudo mv ~/client1.crt ~/cert_authority/pki/private/client1.key ~/client-configs

Step 6: Copy the sample client configuration file to the client configurations directory:

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs

Step 7: Edit the client configuration file:

vim ~/client-configs/client.conf

Update the remote directive on line 42 with your server's IP address or hostname.

Uncomment lines 61 and 62 to adjust privileges.

Comment out lines 88-90 and line 108 to embed certificates and keys directly in the configuration file.

At the end of the file, add these sections, inserting the actual contents of the corresponding files:

<ca>
# Paste the contents of ca.crt here
</ca>

<cert>
# Paste the contents of client1.crt here
</cert>

<key>
# Paste the contents of client1.key here
</key>

key-direction 1
<tls-auth>
# Paste the contents of tls_auth.key here
</tls-auth>

Save and exit the file, then rename it to have a .ovpn extension:

mv client.conf client1.ovpn

Step 8: Transfer the client configuration file to the client machine:

scp ~/client-configs/client1.ovpn user@CLIENT_IP:/path/to/destination

Step 9: On the client machine, you can start the VPN connection from the command line:

sudo openvpn --config client1.ovpn

Alternatively, import the configuration file using your system's network manager.

Step 10: Go to Settings » Network on your client machine.

Click the '+' button under 'VPN' and choose 'Import from file...'. Select the client1.ovpn file.

Click 'Add' to save the VPN connection.

Toggle the VPN connection to 'On' to initiate the connection.

Once connected, verify that your traffic is routing through the VPN:

curl https://ipinfo.io/ip

The returned IP should match your server's IP address.


By completing these steps, you've successfully set up an OpenVPN server on Ubuntu 20.04 and connected a client, ensuring secure access to your network over the internet.