Stunnel + OpenVPN Server on Ubuntu 16.04
By: Jayden Chua
Tags: Networking, Stunnel, VPN, Openvpn, Ubuntu

Pre-requisites

The article assumes you already have a Ubuntu 16.04 machine setup somewhere. This can either be on AWS, DigitalOcean, Linode, Aliyun or any other locations. Here are is the list of articles on how I setup the server with the different cloud providers.

AWS

DigitalOcean

Linode

Aliyun

Azure

Before you read-on, currently, I haven’t found a way to get this to work on iOS. So if anyone knows how to setup a Client on iOS that uses Stunnel and OpenVPN, please share!

Incase you are interested in using Ubuntu 18.04 instead, I’ve also documented my process here.

Installing required software

We will be installing these applications. OpenVPN, Stunnel and Easy-RSA.

$ sudo apt-get install openvpn stunnel4 easy-rsa

Setup OpenVPN Server

Ok, I promise to be quick here. So here are all the steps we need to get done.

1. Install easy-rsa tools

Before we proceed further, we will login as superuser. Use make-cadir to create a the easy-rsa folder where all our tools will reside that will help us with key creation and generation.

$ sudo -s

$ make-cadir /etc/openvpn/easy-rsa

2. Initialize all variables

The first step before any of the tools can be use by running source ./vars in the easy-rsa folder.

$ cd /etc/openvpn/easy-rsa

$ source ./vars

3. Remove all previously created keys

Just to be sure to remove any previously created keys, by running ./clean-all this removes the keys directory in the easy-rsa directory.

$ ./clean-all

4. Build Certificate Authority

This will help sign our certs later on. What is important here is you can hit the return carriage on most of the questions by leaving it as default it shouldn’t matter.

The only important question is “Common Name” remember to set this up. It can be anything that you want. But it cannot be empty or a period. I used period for the rest of the questions. Remember your “Common Name” because we need it for the next step.

$ ./build-ca

Results of running ./build-ca

5. Build Server Keys

Using the “Common Name” that we set up in the last step, we will use it in our command now. Here you will be asked a bunch of questions again, mostly default is fine. The only important thing you need to fill up is the “Common Name”. When it’s asking me for a challenge password, I chose not to use anything, just hit the return carriage. Finally, enter ‘y’ for both question — “Sign the certificate?” and “1 out of 1 certificate requests certified, commit?”.

$ ./build-key-server your-common-name

Results of running ./build-key-server

6. Setup the Diffie–Hellman key exchange

Use ./build-dh to create the DH keys. This is required for key exchanges. This step can take a little while, so be patient.

$ ./build-dh

7. Setup IP forwarding

Now, we need to setup IP forwarding by uncommenting out a line in /etc/sysctl.conf . Change #net.ipv4.ip_forward=1 such that it looks like net.ipv4.ip_forward=1 finally run sysctl -p .

$ nano /etc/sysctl.conf // uncomment this line: net.ipv4.ip_forward=1 by removing the hash symbol before the line $ sysctl -p

How the /etc/sysctl.conf should look like

Result of running “sysctl -p”

8. Setup NAT and persist ip rules

Set up the iptables with the command below. Ensure that we set persist our IP settings so that the next time we reboot, it’s always there.

$ iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE $ apt-get install iptables-persistent

// choose "yes" twice, to keep current IPv4 and IPv6 rules

9. Configure server.conf

Create a new server.conf in /etc/openvpn/ . The contents of this files should be as follows. Replace out the bold text with your own settings. The important 3 lines that needs to be changed are ca /etc/openvpn/easy-rsa/keys/everything-is-awsome.crt , cert /etc/openvpn/easy-rsa/keys/everything-is-awsome.key , push "route x.x.x.x 255.255.255.255 net_gateway" .

x.x.x.x needs to be your IP address of the server where you are currently SSH-ed into.

Note: I’ve recently noticed OpenVPN will by default do a renegotiation on TLS, so to ensure this connection doesn’t break every hour, I’ve added the following directives reneg-sec 0 , if you would like this renegotiation to happen every number of seconds, remember to change this as you like.

$ nano /etc/openvpn/server.conf // Contents of /etc/openvpn/server.conf below cipher AES-128-CBC

port 1194

proto tcp

dev tun

tun-mtu 1500

tun-mtu-extra 32

mssfix 1450 ca /etc/openvpn/easy-rsa/keys/ca.crt

cert /etc/openvpn/easy-rsa/keys/everything-is-awsome.crt

key /etc/openvpn/easy-rsa/keys/everything-is-awsome.key

dh /etc/openvpn/easy-rsa/keys/dh2048.pem server 10.8.0.0 255.255.255.0 push "redirect-gateway def1 bypass-dhcp"

push "route x.x.x.x 255.255.255.255 net_gateway"

push "dhcp-option DNS 1.1.1.1"

push "dhcp-option DNS 8.8.8.8"

push "dhcp-option DNS 8.8.4.4" keepalive 5 30

reneg-sec 0 persist-key

persist-tun

status /var/log/openvpn.log

verb 3

10. Restart OpenVPN server

Finally, restart the openvpn server to check everything was configured correctly.

$ service openvpn restart

Create OpenVPN Client Keys

Next, since we are here, we will also create client keys. I will run through the steps of creating just one client. But you can also repeat the process to create multiple client settings. Incase you need one for each Windows, MacOS, Android.

1. Generate the keys

Run the ./build-key your-client-name to create the corresponding keys for each client. Mostly you can use the default values, but what is important is the “Common Name” again. This time, don’t confuse this with the server common name. This common name refers to the client. So in my case I chose “client1” for this example.

$ sudo -s

$ cd /etc/openvpn/easy-rsa

$ ./build-key client1

IMPORTANT NOTE:

DO NOT run ./build-key without a “client name” parameter, this will result in the following error. 293: shift: can't shift that many

run without a “client name” parameter, this will result in the following error. DO NOT have the same client common name as the server name. This will result in the following error. failed to update database. TXT_DB error number 2

2. Download the Client Files

Next, download these client files which will be used for the setup later. If you have problems with step, research a little on the scp command.

// These commands are ran on the server to copy files over to /tmp

$ cp /etc/openvpn/easy-rsa/keys/ca.crt /tmp

$ cp /etc/openvpn/easy-rsa/keys/client1.* /tmp // These scp commands are meant to be ran on your local machine

$ scp root@your-hostname:/tmp/ca.crt ~/Downloads

$ scp root@your-hostname:/tmp/client1.* ~/Downloads // Clean up after ourselves. Removing what we copied on the server

$ rm -rf /tmp/ca.crt

$ rm -rf /tmp/client1.*

Setup Stunnel Server + Client

This part will be quick. Here are the steps.

1. Generate Certs and Keys

Proceed to /etc/stunnel and generate the keys and certs. Here, what we are doing is to create a new key.pem and cert.pem with a validity period of 10 years. Next, we concatenate both these files into a stunnel.pem file that we need to use it locally later. Finally, in case we want to use this for Android, we also need to convert this into a stunnel.p12 file.

$ sudo -s

$ cd /etc/stunnel/



$ openssl genrsa -out key.pem 2048

$ openssl req -new -x509 -key key.pem -out cert.pem -days 3650

$ cat key.pem cert.pem >> stunnel.pem

$ openssl pkcs12 -export -out stunnel.p12 -inkey key.pem -in cert.pem

2. Configure the Stunnel Server

Here, we need to create a new stunnel.conf file. Most of the content is the same. Just ensure where the stunnel.pem file is actually where you have that stunnel.pem you created in step 1.

$ nano /etc/stunnel/stunnel.conf // Contents of stunnel.conf

pid = /stunnel4.pid

setuid = stunnel4

setgid = stunnel4

socket = l:TCP_NODELAY=1

cert = /etc/stunnel/stunnel.pem [openvpn]

accept = 443

connect = localhost:1194

cert = /etc/stunnel/stunnel.pem

3. Update default/stunnel4

Make the following changes to /etc/default/stunnel4 . Change ENABLED=0 to ENABLED=1 .

Contents of /etc/default/stunnel4

4. Download Client Files

Download /etc/stunnel/stunnel.pem , /etc/stunnel/stunnel.p12 .

$ cp /etc/stunnel/stunnel.pem /tmp

$ cp /etc/stunnel/stunnel.p12 /tmp ..

$ scp root@your-hostname:/tmp/stunnel.* ~/Downloads $ rm -rf /tmp/stunnel.*

Reboot server

Finally, run sudo reboot now and wait for server to reboot.

Configuring Clients

Next, depending on what you need on your client end, you can consider visiting any of the articles below to setup your clients respectively. These articles are currently in work in progress. Will update this section once those articles are ready.

Sharing OpenVPN + Stunnel via Router

If you’re interested you can actually also share the VPN on a router by either connecting a rasberry pi or a spare linux machine in the network as a default gateway. The process was a little tricky for me so I documented how I converted my router into a OpenVPN + Stunnel router, in case this might interest you!

Other Articles in Series

This article is part of a series, see how you might be able to connect OpenVPN and Stunnel through these other different clients and approaches.

References