Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AydinAdn/c05b82fb507370d3e3fb4e1db184ec10 to your computer and use it in GitHub Desktop.
Save AydinAdn/c05b82fb507370d3e3fb4e1db184ec10 to your computer and use it in GitHub Desktop.

Prerequisites

Root access to an Ubuntu 16.04 installation via SSH, first run these commands before anything else.

sudo apt-get update 
sudo apt-get install openvpn easy-rsa 

1. Install OpenVPN Server

To start off, we will install OpenVPN onto our server. OpenVPN is available in Ubuntu’s default repositories, so we can use apt for the installation. We will also be installing the easy-rsa package, which will help us set up an internal CA (certificate authority) for use with our VPN. To update your server’s package index and install the necessary packages type:

sudo apt-get update
sudo apt-get install openvpn easy-rsa 

The needed software is now on the server, ready to be configured.

2. Setup Certificate Authority (CA) directory

Copy the easy-rsa template directory into our home directory with the makecadir command:

make-cadir ~/openvpn-ca 

Move into the newly created directory to begin configuring the CA:

cd ~/openvpn-ca

3. Configure the CA Variables

To configure the values our CA will use, we need to edit the vars file within the directory. Open that file now in your text editor:

nano vars 

Inside, you will find some variables that can be adjusted to determine how your certificates will be created. We only need to worry about a few of these, modify the following values to whatever you want.

export KEY_COUNTRY="**COUNTRYCODE**" 
export KEY_PROVINCE="**PROVINCE**" 
export KEY_CITY="**CITY**" 
export KEY_ORG="**ORG**"
export KEY_EMAIL="**EMAIL@ADDRESS.COM**" 
export KEY_OU="**ORGINIZATIONAL_UNIT**" 

Also change KEY_NAME to server

export KEY_NAME="server" 

Press Ctrl + O to save and Ctrl + X to exit

4. Build the Certificate Authority

Ensure you are in your CA directory, and then source the vars file you just edited:

cd ~/openvpn-ca 
source vars 

Make sure we’re operating in a clean environment by typing:

./clean-all 

Now, we can build our root CA by typing:

./build-ca

This will initiate the process of creating the root certificate authority key and certificate. Since we filled out the vars file, all of the values should be populated automatically. Just press ENTER through the prompts to confirm the selections:

5. Create the Server Certificate, Key, and Encryption Files

Start by generating the OpenVPN server certificate and key pair. We can do this by typing:

./build-key-server server 

Once again, the prompts will have default values based on the argument we just passed in (server) and the contents of our vars file we sourced. Feel free to accept the default values by pressing ENTER. Do not enter a challenge password for this setup. Towards the end, you will have to enter y to two questions to sign and commit the certificate.

Next, we’ll generate a few other items. We can generate a strong Diffie-Hellman keys to use during key exchange by typing:

./build-dh 

Afterwards, we can generate an HMAC signature to strengthen the server’s TLS integrity verification capabilities:

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

6. Generate a Client Certificate and Key Pair Next

Next, we can generate a client certificate and key pair. Although this can be done on the client machine and then signed by the server/CA for security purposes, for this guide we will generate the signed key on the server for the sake of simplicity.

We will generate a single client key/certificate for this guide, but if you have more than one client, you can repeat this process as many times as you’d like. Pass in a unique value to the script for each client.

Because you may come back to this step at a later time, we’ll re-source the vars file. We will use client1 as the value for our first certificate/key pair for this guide.

To produce credentials without a password, to aid in automated connections, use the build-key command like this:

cd ~/openvpn-ca
source vars
./build-key client1

If instead, you wish to create a password-protected set of credentials, use the build-key-pass command:

cd ~/openvpn-ca
source vars 
./build-key-pass client1

Again, the defaults should be populated, so you can just hit ENTER to continue. Leave the challenge password blank and make sure to enter y for the prompts that ask whether to sign and commit the certificate.

7. Configure the OpenVPN Service

Next, we can begin configuring the OpenVPN service using the credentials and files we’ve generated. Copy the Files to the OpenVPN Directory To begin, we need to copy the files we need to the /etc/openvpn configuration directory.

We can start with all of the files that we just generated. These were placed within the ~/openvpnca/keys directory as they were created. We need to move our CA cert, our server cert and key, the HMAC signature, and the Diffie-Hellman file:

cd ~/openvpn-ca/keys 
sudo cp ca.crt server.crt server.key ta.key dh2048.pem /etc/openvpn 

Next, we need to copy and unzip a sample OpenVPN configuration file into configuration directory so that we can use it as a basis for our setup:

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

Adjust the OpenVPN Configuration Now that our files are in place, we can modify the server configuration file:

sudo nano /etc/openvpn/server.conf 

Basic Configuration First, find the HMAC section by looking for the tls-auth directive. Remove the “;” to uncomment the tls-auth line:

tls-auth ta.key 0 # This file is secret 

Next, find the section on cryptographic ciphers by looking for the commented out cipher lines. The AES-128-CBC cipher offers a good level of encryption and is well supported. Remove the “;” to uncomment the cipher AES-128-CBC line:

cipher AES-128-CBC 

Below this, add an auth line to select the HMAC message digest algorithm. For this, SHA256 is a good choice:

auth SHA256 

Finally, find the user and group settings and remove the “;” at the beginning of to uncomment those lines:

user nobody 
group nogroup 

(Optional) Push DNS Changes to Redirect All Traffic Through the VPN The settings above will create the VPN connection between the two machines, but will not force any connections to use the tunnel. If you wish to use the VPN to route all of your traffic, you will likely want to push the DNS settings to the client computers.

You can do this, uncomment a few directives that will configure client machines to redirect all web traffic through the VPN. Find the redirect-gateway section and remove the semicolon “;” from the beginning of the redirect-gateway line to uncomment it:

push "redirect-gateway def1 bypass-dhcp" 

Just below this, find the dhcp-option section. Again, remove the “;” from in front of both of the lines to uncomment them:

push "dhcp-option DNS 208.67.222.222" 
push "dhcp-option DNS 208.67.220.220" 

This should assist clients in reconfiguring their DNS settings to use the VPN tunnel for as the default gateway.

(Optional) Adjust the Port and Protocol By default, the OpenVPN server uses port 1194 and the UDP protocol to accept client connections. If you need to use a different port because of restrictive network environments that your clients might be in, you can change the port option. If you are not hosting web content your OpenVPN server, port 443 is a popular choice since this is usually allowed through firewall rules.

# Optional! 
port 443

Often if the protocol will be restricted to that port as well. If so, change proto from UDP to TCP:

# Optional! 
proto tcp

If you have no need to use a different port, it is best to leave these two settings as their default.

(Optional) Point to Non-Default Credentials

If you selected a different name during the ./build-key-server command earlier, modify the cert and key lines that you see to point to the appropriate .crt and .key files. If you used the default server, this should already be set correctly:

cert server.crt 
key server.key 

When you are finished, save and close the file.

8: Adjust the Server Networking Configuration

Next, we need to adjust some aspects of the server’s networking so that OpenVPN can correctly route traffic. Allow IP Forwarding First, we need to allow the server to forward traffic. This is fairly essential to the functionality we want our VPN server to provide.

We can adjust this setting by modifying the /etc/sysctl.conf file:

sudo nano /etc/sysctl.conf 

Inside, look for the line that sets net.ipv4.ip_forward. Remove the “#” character from the beginning of the line to uncomment that setting:

net.ipv4.ip_forward=1 

Save and close the file when you are finished. To read the file and adjust the values for the current session, type:

sudo sysctl -p 

Adjust the UFW Rules to Masquerade Client Connections

If you followed the Ubuntu 16.04 initial server setup guide in the prerequisites, you should have the UFW firewall in place. Regardless of whether you use the firewall to block unwanted traffic (which you almost always should do), we need the firewall in this guide to manipulate some of the traffic coming into the server. We need to modify the rules file to set up masquerading, an iptables concept that provides on-the-fly dynamic NAT to correctly route client connections.

Before we open the firewall configuration file to add masquerading, we need to find the public network interface of our machine. To do this, type:

ip route | grep default 

Your public interface should follow the word “dev”. For example, this result shows the interface named wlp11s0, which is highlighted below:

Output default via 203.0.113.1 dev wlp11s0 proto static metric 600

When you have the interface associated with your default route, open the /etc/ufw/before.rules file to add the relevant configuration:

sudo nano /etc/ufw/before.rules

This file handles configuration that should be put into place before the conventional UFW rules are loaded. Towards the top of the file, add the highlighted lines below. This will set the default policy for the POSTROUTING chain in the nat table and masquerade any traffic coming from the VPN:

Note: Remember to replace wlp11s0 in the -A POSTROUTING line below with the interface you found in the above command.

#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#

# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to wlp11s0 (change to the interface you discovered!)
-A POSTROUTING -s 10.8.0.0/8 -o wlp11s0 -j MASQUERADE
COMMIT
# END OPENVPN RULES

# Don't delete these required lines, otherwise there will be errors
*filter

Save and close the file when you are finished.

We need to tell UFW to allow forwarded packets by default as well. To do this, we will open the /etc/default/ufw file:

sudo nano /etc/default/ufw

Inside, find the DEFAULT_FORWARD_POLICY directive. We will change the value from DROP to ACCEPT:

DEFAULT_FORWARD_POLICY="ACCEPT"

Save and close the file when you are finished.

Open the OpenVPN Port and Enable the Changes

Next, we’ll adjust the firewall itself to allow traffic to OpenVPN.

If you did not change the port and protocol in the /etc/openvpn/server.conf file, you will need to open up UDP traffic to port 1194. If you modified the port and/or protocol, substitute the values you selected here.

We’ll also add the SSH port in case you forgot to add it when following the prerequisite tutorial:

sudo ufw allow 1194/udp
sudo ufw allow OpenSSH

Now, we can disable and re-enable UFW to load the changes from all of the files we’ve modified:

sudo ufw disable
sudo ufw enable

Our server is now configured to correctly handle OpenVPN traffic.

9. Start and Enable the OpenVPN Service

We’re finally ready to start the OpenVPN service on our server. We can do this using systemd.

We need to start the OpenVPN server by specifying our configuration file name as an instance variable after the systemd unit file name. Our configuration file for our server is called /etc/openvpn/server.conf, so we will add @server to end of our unit file when calling it:

sudo systemctl start openvpn@server

Double-check that the service has started successfully by typing:

sudo systemctl status openvpn@server

You can also check that the OpenVPN tun0 interface is available by typing:

ip addr show tun0

You should see a configured interface.
If everything went well, enable the service so that it starts automatically at boot:

sudo systemctl enable openvpn@server    

10. Create Client Configuration Infrastructure

Next, we need to set up a system that will allow us to create client configuration files easily.

Creating the Client Config Directory Structure Create a directory structure within your home directory to store the files:

mkdir -p ~/client-configs/files

Since our client configuration files will have the client keys embedded, we should lock down permissions on our inner directory:

chmod 700 ~/client-configs/files

Creating a Base Configuration

Next, let’s copy an example client configuration into our directory to use as our base configuration:

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

Open this new file in your text editor:

nano ~/client-configs/base.conf

Inside, we need to make a few adjustments.

First, locate the remote directive. This points the client to our OpenVPN server address. This should be the public IP address of your OpenVPN server. If you changed the port that the OpenVPN server is listening on, change 1194 to the port you selected:

remote server_IP_address 1194

Be sure that the protocol matches the value you are using in the server configuration:

proto udp

Next, uncomment the user and group directives by removing the “;”:

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nogroup

Find the directives that set the ca, cert, and key. Comment out these directives since we will be adding the certs and keys within the file itself:

# SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
#ca ca.crt
#cert client.crt
#key client.key

Mirror the cipher and auth settings that we set in the /etc/openvpn/server.conf file:

cipher AES-128-CBC
auth SHA256

Next, add the key-direction directive somewhere in the file. This must be set to “1” to work with the server:

key-direction 1

Finally, add a few commented out lines. We want to include these with every config, but should only enable them for Linux clients that ship with a /etc/openvpn/update-resolv-conf file. This script uses the resolvconf utility to update DNS information for Linux clients.

# script-security 2
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf

If your client is running Linux and has an /etc/openvpn/update-resolv-conf file, you should uncomment these lines from the generated OpenVPN client configuration file.

Save the file when you are finished.

Creating a Configuration Generation Script

Next, we will create a simple script to compile our base configuration with the relevant certificate, key, and encryption files. This will place the generated configuration in the ~/client-configs/files directory.

Create and open a file called make_config.sh within the ~/client-configs directory:

nano ~/client-configs/make_config.sh

Inside, paste the following script:

#!/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 '<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

Save and close the file when you are finished.

Mark the file as executable by typing:

chmod 700 ~/client-configs/make_config.sh

11. Generate Client Configurations

Now, we can easily generate client configuration files.

If you followed along with the guide, you created a client certificate and key called client1.crt and client1.key respectively by running the ./build-key client1 command in step 6. We can generate a config for these credentials by moving into our ~/client-configs directory and using the script we made:

cd ~/client-configs
./make_config.sh client1

If everything went well, we should have a client1.ovpn file in our ~/client-configs/files directory:

ls ~/client-configs/files

Transferring Configuration to Client Devices

We need to transfer the client configuration file to the relevant device. For instance, this could be your local computer or a mobile device.

While the exact applications used to accomplish this transfer will depend on your choice and device’s operating system, you want the application to use SFTP (SSH file transfer protocol) or SCP (Secure Copy) on the backend. This will transport your client’s VPN authentication files over an encrypted connection.

Here is an example SFTP command using our client1.ovpn example. This command can be run from your local computer (Windows). It places the .ovpn file in your home directory:

sftp user@openvpn_server_ip
get client-configs/files/client1.ovpn

The original of this process can be found on https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04 and this gist was created as reference in case the original was ever to be lost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment