How to Set Up OpenVPN with Stunnel on Ubuntu 24.04 Server

This tutorial is going to show you how to run your own OpenVPN server on Ubuntu 24.04. OpenVPN is an open-source, robust, and highly flexible VPN solution. Stunnel is a tool that tunnels OpenVPN traffic over TCP port 443 in TLS mode, to bypass firewall blocking.

Why Set Up Your Own VPN Server?

  • Maybe you are a VPN service provider or a system administrator, which behooves you to set up your own VPN server.
  • You don’t trust the no-logging policy of VPN service providers, so you go the self-host route.
  • You can use VPN to implement network security policy. For example, if you run your own email server, you can require users to log in only from the IP address of the VPN server by creating an IP address whitelist in the firewall. Thus, your email server is hardened to prevent hacking activities.
  • Perhaps you are just curious to know how VPN server works.

Set Up OpenVPN with Stunnel on Ubuntu

Features of OpenVPN Server

  • Lightweight and fast. In my test, I can watch YouTube 4K videos with OpenVPN. YouTube is blocked in my country (China).
  • Runs on Linux and most BSD servers.
  • There is OpenVPN client software for Linux, macOS, Windows, Android, and iOS, and OpenWRT.
  • Supports RADIUS accounting.
  • Supports virtual hosting (multiple domains).
  • Easy to set up
  • Supports SSL/TLS security, ethernet bridging, TCP or UDP tunnel transport through proxies or NAT.
  • Support for dynamic IP addresses and DHCP
  • Scalability to hundreds or thousands of users
  • Supports conventional encryption using a pre-shared secret key (Static Key mode) or public key security (SSL/TLS mode) using client & server certificates

Requirements

To follow this tutorial, you will need a VPS (Virtual Private Server) that can access blocked websites freely (Outside of your country or Internet filtering system). I recommend Kamatera VPS, which features:

  • 30 days free trial.
  • Starts at $4/month (1GB RAM)
  • High-performance KVM-based VPS
  • 9 data centers around the world, including United States, Canada, UK, Germany, The Netherlands, Hong Kong, and Isreal.

Follow the tutorial linked below to create your Linux VPS server at Kamatera.

Once you have a VPS running Ubuntu 24.04, follow the instructions below.

Step 1: Install OpenVPN Server on Ubuntu 24.04

Log into your Ubuntu 24.04 server. Then use apt to install the openvpn package from the default Ubuntu repository.

sudo apt update
sudo apt install -y openvpn openvpn-systemd-resolved easy-rsa

Step 2: Set Up Certificate Authentication in OpenVPN

OpenVPN supports password authentication (pre-shared key), but it’s very limited. You can generate only one pre-share key. To support multiple users, we need to use certificate authentication. Each user will have their own certificate.

To accomplish this, we need to set up a public key infrastructure (PKI), which includes:

  • Set up a certificate authority (CA)
  • Create server key and certificate
  • Create client key and certificate

Set up a certificate authority (CA)

A certificate authority issues server certificates and client certificates. For example, Let’s Encrypt is a certificate authority that issues free TLS server certificates. However, Let’s Encrypt doesn’t issue client certificates, so we need to set up a private certificate authority for OpenVPN.

The openssl utility is widely used to set up a certificate authority, but its command line syntax is complex. Instead, we can use the easy-rsa utility, which is installed in step 1. As its name implies, it’s easier than openssl.

First, run the following command to copy the /usr/share/easy-rsa/ directory to /etc/openvpn/.

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

Switch to the root user.

sudo su -

Change to the /etc/openvpn/easy-rsa/ directory.

cd /etc/openvpn/easy-rsa/

Initialize a public key infrastructure.

./easyrsa init-pki

OpenVPN Initialize a public key infrastructure

Then create a certificate authority.

./easyrsa build-ca

You will be asked to enter a passphrase for the CA. When asked about setting a common name for the CA, you can press Enter to choose the default name: Easy-RSA CA.

ubuntu 24.04 easyrsa build-ca

Create server key and certificate

Generate a keypair and certificate request for the OpenVPN server. Replace openvpn.example.com with a real sub-domain for your OpenVPN server. You will need to enter a common name. Use this subdomain as the common name.

./easyrsa gen-req openvpn.example.com nopass

Ubuntu 24.04 openvpn Create server key and certificate

Generate Diffie Hellman parameters.

./easyrsa gen-dh

easy rsa Generate Diffie Hellman parameters

Now sign the certificate request. The server certificate will be created.

./easyrsa sign-req server openvpn.example.com

easy rsa sign certificate request

Generate an OpenVPN static key to enhance SSL/TLS security.

openvpn --genkey tls-auth /etc/openvpn/easy-rsa/pki/ta.key

Create client key and certificate

Generate a certificate request for the user user01.

./easyrsa gen-req user01 nopass

openvpn Generate a certificate request.

Sign this certificate request. The client certificate will be created. You will need to enter the CA passphrase.

./easyrsa sign-req client user01

openvpn Create client key and certificate

Each VPN user should have their own certificate/key.

Step 3: Edit OpenVPN Server Configuration File

Copy the sample server configuration file.

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

Edit this file.

sudo nano /etc/openvpn/server.conf

At the beginning of this file, you can find the following line, which enables UDP port on the server’s public IPv4 address.

proto udp

Add a second directive to support IPv6.

proto udp
proto udp6

Then find the following lines.

ca ca.crt
cert server.crt
key server.key # This file should be kept secret

The 3 lines specify the location of the CA certificate, server certificate, and server private key. We need to use the actual location.

ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/openvpn.linuxbabe.com.crt
key /etc/openvpn/easy-rsa/pki/private/openvpn.linuxbabe.com.key

Then find the Diffie hellman parameters setting.

dh dh2048.pem

Change it to:

dh /etc/openvpn/easy-rsa/pki/dh.pem

The following line specifies the private IPv4 network for OpenVPN. The OpenVPN server will have the 10.8.0.1 private IP address.

server 10.8.0.0 255.255.255.0

Add a second directive to enable IPv6 private addressing.

server 10.8.0.0 255.255.255.0
server-ipv6 2001:db8:0:123::/64

By default, OpenVPN uses the net30 network topology, which is deprecated. Find the follownig line.

;topology subnet

Uncomment it to use the subnet network topology.

topology subnet

Find the following line

;push "redirect-gateway def1 bypass-dhcp"

Uncomment it (remove the beginning semicolon) and also add a second push directive, so the OpenVPN server will become the gateway for VPN clients. They will also use the OpenVPN as the DNS server.

push "redirect-gateway def1 bypass-dhcp"
push "route-ipv6 2000::/3"

If you want VPN clients to use a particular DNS server, find the following two lines.

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

Uncomment them and change the DNS server IP address.

push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 1.1.1.1"

Find the following line.

;client-to-client

Uncomment it, so VPN clients can ping each other.

client-to-client

Finally, find the following line.

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

Specify the actual location of OpenVPN static key.

tls-auth /etc/openvpn/easy-rsa/pki/ta.key 0

Save and close the file. Start OpenVPN server.

sudo systemctl enable --now openvpn@server

Check its status:

sudo systemctl status openvpn@server

Output:

 [email protected] - OpenVPN connection to server
     Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled; preset: enabled)
     Active: active (running) since Sun 2024-05-19 17:31:35 HKT; 34s ago
       Docs: man:openvpn(8)
             https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
             https://community.openvpn.net/openvpn/wiki/HOWTO
   Main PID: 6114 (openvpn)
     Status: "Initialization Sequence Completed"
      Tasks: 1 (limit: 10)
     Memory: 1.4M (peak: 1.7M)
        CPU: 99ms
     CGroup: /system.slice/system-openvpn.slice/[email protected]
             └─6114 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/server.conf --writepid /run/openvpn/server.pid

As you can see, it’s active (running) and automatic start at boot time is enabled.

Step 4: Enable IP Forwarding

For the VPN server to route packets between VPN clients and the Internet, we need to enable IP forwarding by running the following command.

echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/60-custom.conf

Also, run the following two commands to enable TCP BBR algorithm to boost TCP speed.

echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.d/60-custom.conf

echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.d/60-custom.conf

Then apply the changes with the below command. The -p option will load sysctl settings from /etc/sysctl.d/60-custom.conf file. This command will preserve our changes across system reboots.

sudo sysctl -p /etc/sysctl.d/60-custom.conf

Step 5: Configure IP Masquerading in Firewall

We need to set up IP masquerading in the server firewall, so that the server becomes a virtual router for VPN clients. I will use UFW, which is a front end to the iptables/nftable firewall. Install UFW on Ubuntu with:

sudo apt install ufw

First, you need to allow SSH traffic.

sudo ufw allow 22/tcp

Then find the name of your server’s main network interface.

ip addr

As you can see, it’s named ens3 on my Ubuntu server.

openconnect-ubuntu 20.04-command-line

To configure IP masquerading, we have to add iptables command in a UFW configuration file.

sudo nano /etc/ufw/before.rules

By default, there are some rules for the filter table. Add the following lines at the end of this file. Replace ens3 with your own network interface name.

# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE

# End each table with the 'COMMIT' line or these rules won't be processed
COMMIT

In Nano text editor, you can go to the end of the file by pressing Ctrl+W, then pressing Ctrl+V.

ufw masquerade rule openvpn ubuntu

The above lines will append (-A) a rule to the end of POSTROUTING chain of nat table. It will link your virtual private network with the Internet. And also hide your network from the outside world. So the Internet can only see your VPN server’s IP, but can’t see your VPN client’s IP, just like your home router hides your private home network.

By default, UFW forbids packet forwarding. We can allow forwarding for our private network. Find the ufw-before-forward chain in this file and add the following 3 lines, which will accept packet forwarding if the source IP or destination IP is in the 10.8.0.0/24 range.

# allow forwarding for trusted network
-A ufw-before-forward -s 10.8.0.0/24 -j ACCEPT
-A ufw-before-forward -d 10.8.0.0/24 -j ACCEPT

ufw allow packet forwarding openvpn

Save and close the file. Then enable UFW.

sudo ufw enable

If you have enabled UFW before, then you can use systemctl to restart UFW.

sudo systemctl restart ufw

Now if you list the rules in the POSTROUTING chain of the NAT table by using the following command:

sudo iptables -t nat -L POSTROUTING

You can see the Masquerade rule.

openvpn-IP-Masquerading-ufw-ubuntu

It can take some time for UFW to process the firewall rules. If the masquerade rule doesn’t show up, then restart UFW again (sudo systemctl restart ufw).

Step 6: Open Port 1194 in Firewall

Run the following command to open TCP and UDP port 1194.

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

Now OpenVPN server is ready to accept client connections.

If you run a local DNS Resolver

For those of you who run a local DNS resolver, if you specified 10.8.0.1 as the DNS server for VPN clients, then you must allow VPN clients to connect to port 53 with the following UFW rule.

sudo ufw insert 1 allow in from 10.8.0.0/24

You also need to edit the BIND DNS server’s configuration file (/etc/bind/named.conf.options) to allow VPN clients to send recursive DNS queries like below.

allow-recursion { 127.0.0.1; 10.8.0.0/24; };

Then restart BIND.

sudo systemctl restart named

How to Install and Use OpenVPN client on Ubuntu 24.04 Desktop

Run the following command to install OpenVPN command line client on Ubuntu desktop.

sudo apt install openvpn

Then you need to copy the CA certificate, client certificate, client private key, and the static key file from the OpenVPN server to the client’s computer. The path for the files on the OpenVPN server.

  • CA cert: /etc/openvpn/easy-rsa/pki/ca.crt
  • Client cert: /etc/openvpn/easy-rsa/pki/issued/user01.crt
  • Client key: /etc/openvpn/easy-rsa/pki/private/user01.key
  • Static key: /etc/openvpn/easy-rsa/pki/ta.key

I stored them under the /etc/openvpn/client/ directory on the client’s computer.

Next, copy the sample client config file.

sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/

Edit the file.

sudo nano /etc/openvpn/client.conf

Find the following lines.

remote my-server-1 1194

Specify the public IP address of your OpenVPN server.

remote 12.34.56.78 1194

Then find the following lines.

ca ca.crt
cert client.crt
key client.key

Use the actual path for the CA cert, client cert, and client private key.

ca /etc/openvpn/client/ca.crt
cert /etc/openvpn/client/user01.crt
key /etc/openvpn/client/user01.key

Find the following line.

tls-auth ta.key 1

Use the actual path for the static key.

tls-auth /etc/openvpn/client/ta.key 1

Save and close the file. Then start the OpenVPN client

sudo systemctl start openvpn@client

Check status:

sudo systemctl status openvpn@client

ubuntu 24.04 sudo systemctl status openvpn@client

Check if you can ping the OpenVPN server.

ping 10.8.0.1

Then go to https://icanhazip.com. If everything is working properly, you should see the public IP address of the OpenVPN server.

If you are successfully connected to the VPN server, but your public IP address doesn’t change, that’s because IP forwarding or IP masquerading is not working. I once had a typo in my iptables command (using a wrong IP address range), which caused my computer not being able to browse the Internet.

To stop this Systemd service, run

sudo systemctl stop openvpn@client

If you want to use Network Manager to manage OpenVPN connection, then you also need to install these packages.

sudo apt install network-manager-openvpn network-manager-openvpn-gnome

OpenVPN GUI Client for Windows and macOS

You can use the free and open-source Pritunl OpenVPN client: https://client.pritunl.com/

Speed

OpenVPN is pretty fast. I can use it to watch 4k videos on YouTube. As you can see, my connection speed is 63356 Kbps, which translates to 61 Mbit/s.

ocserv vpn speed test singapore server

And here’s the test results on speedtest.net.

ocserv vpn speed test singapore

Debugging

If there’s problem establishing VPN connection, you can edit the OpenVPN server config file (/etc/openvpn/server.conf) and increase the level of log file verbosity to 6.

verb 6

This directive is located at the bottom of the file.

Then you can check the logs.

  • client: sudo journalctl -eu openvpn@client
  • server: sudo journalctl -eu openvpn@server

Set Up Stunnel (optional)

If you live in a country like China, or Iran, then your national firewall may block OpenVPN connections. You can wrap the OpenVPN traffic inside a TLS tunnel to hide the fact that you are using OpenVPN.

Configure Stunnel on the OpenVPN server

Edit the OpenVPN server config file.

sudo nano /etc/openvpn/server.conf

Enable the TCP port.

proto tcp
proto udp
proto udp6

Save and close the file. Then install Stunnel on the OpenVPN server.

sudo apt install -y stunnel4

Copy the sample configuration file:

sudo cp /usr/share/doc/stunnel4/examples/stunnel.conf-sample /etc/stunnel/openvpn.conf

Edit the new file.

sudo nano /etc/stunnel/openvpn.conf

Find the following lines and uncomment them.

;setuid = stunnel4
;setgid = stunnel4

;pid = /var/run/stunnel.pid

;output = /var/log/stunnel.log

Change them to:

setuid = stunnel4
setgid = stunnel4

pid = /var/run/stunnel/stunnel.pid

output = /var/log/stunnel/stunnel.log

Find the following lines.

[gmail-pop3]
client = yes
accept = 127.0.0.1:110
connect = pop.gmail.com:995
verifyChain = yes
CApath = /etc/ssl/certs
checkHost = pop.gmail.com
OCSPaia = yes

[gmail-imap]
client = yes
accept = 127.0.0.1:143
connect = imap.gmail.com:993
verifyChain = yes
CApath = /etc/ssl/certs
checkHost = imap.gmail.com
OCSPaia = yes

[gmail-smtp]
client = yes
accept = 127.0.0.1:25
connect = smtp.gmail.com:465
verifyChain = yes
CApath = /etc/ssl/certs
checkHost = smtp.gmail.com
OCSPaia = yes

This enables tunnels for SMTP, IMAP, and POP3 server. Delete them and add the following lines instead, so Stunnel will be able to pass traffic to the OpenVPN server listen on port 1194.

[openvpn]
cert=/etc/openvpn/easy-rsa/pki/issued/openvpn.example.com.crt
key=/etc/openvpn/easy-rsa/pki/private/openvpn.example.com.key
accept = 0.0.0.0:443
connect = 127.0.0.1:1194

Save and close the file.

Create the PID file and log file.

sudo mkdir /var/run/stunnel /var/log/stunnel

Grant permission to the user.

sudo chown stunnel4:stunnel4 /var/run/stunnel/ -R
sudo chown stunnel4:stunnel4 /var/log/stunnel/ -R
sudo setfacl -R -m u:stunnel4:rx /etc/openvpn/easy-rsa/

Start Stunnel.

sudo /usr/bin/stunnel4 /etc/stunnel/openvpn.conf

You should see that Stunnel is using port 443.

sudo ss -lnpt | grep 443

If it failed to start, then check the log file: /var/log/stunnel/stunnel.log. If your server has another process listening on TCP port 443, you need to stop it, or Stunnel won’t be able to bind to TCP port 443.

Open TCP port 443 in firewall, so VPN clients will be able to connect to this port.

sudo ufw allow 443/tcp

Configure Stunnel on the OpenVPN client

Install Stunnel on the OpenVPN client.

sudo apt install -y stunnel4

Create Stunnel config file.

sudo nano /etc/stunnel/client.conf

Add the following lines in this file.

output = /var/log/stunnel/stunnel.log
pid = /var/run/stunnel/stunnel.pid
client = yes
[openvpn]
sni = openvpn.example.com
accept = 127.0.0.1:1194
connect = 12.34.56.78:443

Save and close the file. Create the log directory and pid directory.

sudo mkdir /var/log/stunnel/ /var/run/stunnel/

Start the Stunnel client.

sudo stunnel /etc/stunnel/client.conf

It listens on 127.0.0.1:1194 and passes requests to the Stunnel server.

sudo ss -lnpt | grep 1194

Next, edit the OpenVPN client config file.

sudo nano /etc/openvpn/client.conf

Enable TCP and disable UDP.

proto tcp
;proto udp

Change remote server address to 127.0.0.1:1194.

remote 127.0.0.1 1194

Save and close the file. Then restart OpenVPN client.

Wrapping Up

That’s it! I hope this tutorial helped you install and configure OpenVPN on Ubuntu 24.04. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks 🙂

Rate this tutorial
[Total: 0 Average: 0]

One Response to “How to Set Up OpenVPN with Stunnel on Ubuntu 24.04 Server

  • Pt_Lutin
    4 seconds ago

    Thanks for this tutorial
    I performed the installation and I have an error in the log :

    2024-07-01 18:19:29 Authenticate/Decrypt packet error: packet HMAC authentication failed
    2024-07-01 18:19:29 TLS error : incoming packet authentication failed from [AF_INET6]::ffff:IP:35296
    2024-07-01 18:19:31 Packet authentication/decryption error: packet HMAC authentication failed
    2024-07-01 18:19:31 TLS error: incoming packet authentication failed from [AF_INET6]::ffff:IP:35296
    2024-07-01 18:19:35 Packet authentication/decryption error: packet HMAC authentication failed
    2024-07-01 18:19:35 TLS error: incoming packet authentication failed from [AF_INET6]::ffff:IP:35296
    2024-07-01 18:19:43 Packet authentication/decryption error: packet HMAC authentication failed
    2024-07-01 18:19:43 TLS error: incoming packet authentication failed from [AF_INET6]::ffff:IP:35296

    I’ve checked everything, but I can’t seem to unblock the situation. Do you have an idea ?

    Translated with DeepL.com (free version)

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here