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.
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
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.
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
Generate Diffie Hellman parameters.
./easyrsa gen-dh
Now sign the certificate request. The server certificate will be created.
./easyrsa sign-req server openvpn.example.com
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
Sign this certificate request. The client certificate will be created. You will need to enter the CA passphrase.
./easyrsa sign-req client user01
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.
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
.
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
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.
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
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.
And here’s the test results on speedtest.net.
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 🙂
Thanks for this tutorial
I performed the installation and I have an error in the log :
I’ve checked everything, but I can’t seem to unblock the situation. Do you have an idea ?
Translated with DeepL.com (free version)
Use tls-crypt instead of tls-auth in server.conf and instead of in client.conf
HI
excellent tutorial.
can you please inform what files are required for client OPENVPN to connect to server
thank you
You can include both the CA certificate (Certificate Authority) and the TA certificate (TLS Authentication certificate) in the OpenVPN client configuration file (.ovpn).
This is a common practice to simplify the distribution and management of certificates. User specific certs as well.
—–BEGIN CERTIFICATE—–
—–BEGIN CERTIFICATE—–
—–BEGIN PRIVATE KEY—–
—–BEGIN OpenVPN Static key V1—–