OpenVPN Server on Ubuntu 16.04


Hello everyone! Hope everyone is having a good start to summer. I’ve been extremely busy as usual, but I had a moment of time to start this new HOWTO, How to Install OpenVPN in Ubuntu 16.04 so that you can connect to your home machines or browse the Internet safely from anywhere in the world. If you don’t know what a VPN, or Virtual Private Network is, this is a simple answer. Its a Network that allows encrypted information between the VPN server and your machine so that it appears like it is on the same network as the rest of your home equipment, but are over the internet. This is useful if you are working remote and need access to your servers at home, but don’t have them connected directly to the Internet with their own IP address.

The main reason I am writing this, is because I had to setup a VPN connection to my home lab so that my co-workers could connect to the various network equipment I have in my lab and test on this equipment. So I setup a VPN so that they can connect into my lab, get on the switches, get on the console concentrator, and power up, power down, and work on the switches remotely. It’s extremely secure since I have to give the user a certificate to connect to my VPN server and I control them so that if they don’t need access anymore, I kill that certificate in my Certificate Authority and they can no longer login on my network.

This HowTo is going to show how I setup OpenVPN on Ubuntu 16.04, and secured the system using UFW so that only 2 ports are exposed to the world to limit the attack surface of my VPN server.First thing I did was install Ubuntu Server 16.04. I used Virtual Machines quite extensively, so that is how this started. I created a VM, made sure to set it’s network interface to my external IP pool, gave it 1GB of RAM and 1 vCPU, 16GB of storage and installed Ubuntu on it. The only other software I installed was OpenSSH-Server and that was completed. I then modified the /etc/network/interfaces file so that it had a static IP address, gateway and DNS server information, subnet range, and what the device was called. This is important since it will come into play when you are setting up the the VPN server so that it knows what to tunnel through for the firewall rules. In this example, the device is ens160, but it will be whatever your system calls it, typically this is eth0.

After the server was installed, I ran the following to make sure it was all up to date and had the latest repositories:

sudo apt update && sudo apt upgrade -y

I reboot the server after this so that it used the new IP address, and was running with the latest updates.

I than ran sudo apt install openvpn easy-rsa to install the required binaries I needed.

I than ran make-cadir ~/openvpn-ca. This command creates the minimum config files and sources so that you can build a Certificate Authority (CA) on the system. This is required to create the certificates that will be used by the server and the clients to connect and verify the systems so that they trust each other.

Once that completes, change directory to the CA folder cd ~/openvpn-ca, and modify the vars file vi vars. Go to the section that looks like this:

export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"

Modify these variables for your needs. Also, find the variable KEY_NAME and change it to the name of your server.

export KEY_NAME="server"

Now, you are ready to build the CA. Run source vars and you should get the following output:

NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/wililupy/openvpn-ca/keys

Go ahead and run ./clean-all to make sure that the environment is good to go. Now we are ready to build the CA. Run the command ./build-ca.

You will be given a bunch of options, most of which you already set in the vars file, so just hit enter to accept them.

We now are ready to create the server certificate, the key and encryption files. This is done with the command ./build-key-server server where server is the name of your VPN server. Once again, it looks at the vars file and uses those for the defaults, and then it will have two prompts you need to answer. The first one is:

Certificate is to be certified until June 13 15:26:11 2026 GMT (3650 days)
Sign the certificate? [y/n]:y

The second one is:

1 out of 1 certificate requests certified, commit? [y/n]y

It will update the database and now we are ready to generate the encryption key. Use the command ./build-dh to do this. It takes about 2 minutes for this command to complete. You will see …. and * while it randomizes. Lastly, we need to generate the HMAC signature. To do this use the following command:

openvpn --genkey --secret keys/ta.key

Now we are ready to build the client certificate so that you can connect to your VPN server. While still in the ~/openvpn-ca directory, and while you are still sourced to vars, run ./build-key client where client is the hostname of the client machine/username. Make sure you say Y at the prompts to sign the certificate and commit the certificate.

You are now ready to copy the required files to the /etc/openvpn directory so that we can configure openvpn to run.

Go into the keys directory:

cd ~/openvpn-ca/keys and copy the certificates and keys to /etc/openvpn

sudo cp ca.crt ca.key server.crt server.key ta.key dh2048.pem /etc/openvpn

We are now ready to copy the example server.conf file to the /etc/openvpn directory so that we can configure the server. You have to uncompress it first:

gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz | sudo tee /etc/openvpn/server.conf

Now we have to modify the file so that it works with our environment.

sudo vi /etc/openvpn/server.conf

Search for redirect-gateway and remove the ; to uncomment the setting so that it looks like this:

push "redirect-gateway def1 bypass-dhcp"

Then below that is the “dhcp-option DNS” settings. Uncomment them and set them to your DNS servers or leave them as the defaults. I changed them to my internal DNS so that users can use my internal names of my systems and get to them easier than searching around for IP addresses. Next, uncomment the HMAC section by searching for tls-auth and just under that variable, add key-direction 0. Last, search for user and uncomment user nobody and group nogroup so that the service knows who to run as.

Now we have to allow the system to do IP Forwarding and modify the Firewall to secure the system. First, modify /etc/sysctl.conf and uncomment net.ipv4.ip_forward=1 and then save the file and run sudo sysctl -p to make the changes take effect.

Next, modify the /etc/ufw/before.rules so we can setup Masquerading for the VPN server. Right after the #  ufw-before-forward option, enter the following:

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

Remember when I said to remember your network device from when we were setting up the static IP of the server? After the -o option in the before-rules file, that is where the name of your device goes. Save the file. Now we have to set UFW to forward by default. Modify the /etc/default/ufw file and find the DEFAULT_FORWARD_POLICY and set it to "ACCEPT". Save this file and now all we have to do is allow ufw the openvpn port and protocol and enable the ssh variable:

sudo ufw allow 1194/udp
sudo ufw allow 22/tcp

Now we need to disable and re-enable ufw so that it will read the changes in the files we modified:

sudo ufw disable
sudo ufw enable

Now we are ready to start OpenVPN. Since our configuration is called server.conf, when we start openvpn, we will tell it @server so that it will use that configuration. Nice this about openvpn, is that we can have multiple configuration, and multiple instances of the VPN server running, all we have to do is trail @configname after it and it will run that config. To start openvpn, run the following command:

sudo systemctl start openvpn@server

Check that it is running by running sudo systemctl status openvpn@server and look for the Active: active (running). If everything looks good, set it to run at startup by running sudo systemctl enable openvpn@server.

Now we are ready to setup the clients. First thing I did was create a new directory for the client files so that I could scp them to my colleagues and my different machines and devices (OpenVPN works on Windows, MacOSX, Linux, iPhone, and Android)

mkdir -p ~/client-configs/files

Also, because there will be multiple keys in this folder for different machines, I locked it down so that only I had access to that folder: chmod 700 ~/client-configs/files.

Next, I copied the example configuration for clients to this location:

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf and then edited the file to meet my client needs.

First thing is to search for remote in the file and change the server_IP_address to the public IP address of your VPN server. Next uncomment the user and group variables by deleting the leading ‘;’.

Next, search for the ca.crt and client.crt sections and comment them out with the ‘#’, and finally, add the key-direction 1 in the file somewhere so that it knows how to use the keys. Save the file and you’re done.

Now, I found this really cool script at https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04.

#!/bin/bash

# First argument: Client identifier

KEY_DIR=~/openvpn-ca/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf

cat ${BASE_CONFIG} \
    <(echo -e '') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '\n') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '\n') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '\n') \
    ${KEY_DIR}/ta.key \
    <(echo -e '') \
    > ${OUTPUT_DIR}/${1}.ovpn

Create a file called make_config.sh and paste the script into that file. Save the file, then make it executable by running chmod 700 ~/client-configs/make_config.sh.

If you remember, we created a client certificate and key previously, using the build-key client command. This created a client.key file in the ~/openvpn-ca/keys directory. We are now going to build a configuration for the VPN that uses these keys. Make sure you are in the ~/client-configs directory and run ./make_config.sh client where client is the name of the client configuration you are creating. The name should match what you entered in the build-key command previously. This will generate a file called client.ovpn which needs to be copied to the client. I use SCP or SFTP to transfer the files between Linux and MacOSX, but for Windows or IOS or Android, getting the certificate file on the system may be a little trickier. For Windows, I use FileZilla or WinSCP. Just login to the VPN server and copy the ovpn file to your home directory on the system.

In Ubuntu Desktop 16.04, make sure you have OpenVPN installed, (sudo apt install network-manager-openvpn-gnome) open up Network Manager, go to VPN Connections, Configure VPN, and click Add. From the drop down, select Import a saved VPN configuration… and browse to your .ovpn file. Select Open and verify that everything looks right, the vpn server’s IP address, the name of the certificates, and click Save. Now you are ready to test. Connect your new VPN and verify that you connect successfully. Check your network devices for the new tun0 device and IP address of 10.8.0.x (ifconfig tun0). Try to connect to a server in your internal network and verify that everything is working as normal.

And thats it. It really isn’t that difficult to setup. If you have any questions, or if this blog helped you in anyway, let me know. I like to think that I’m helping someone out there.

Thanks!

[ayssocial_buttons id=”2″]


8 responses to “OpenVPN Server on Ubuntu 16.04”

  1. Excellent submit, very informative. I’m wondering why the opposite specialists of this sector don’t notice this. You must continue your writing. I am sure, you’ve a huge readers’ base already!|What’s Happening i’m new to this, I stumbled upon this I have discovered It positively useful and it has aided me out loads. I hope to give a contribution & aid different users like its aided me. Great job.

  2. Thank you for publishing this great article. I’m a long time reader but I’ve never actually left
    a comment. I’ve bookmarked your site and shared this on my Facebook.
    Thanks again for a quality post!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.