Onto Part 2 of my series on VPNs, this guide will show you how to set up an OpenVPN server on my Linux distribution of choice, Debian.
Debian is available as an image on a lot of VPS providers, and even services like Amazon AWS and Microsoft Azure, making it the perfect base to start your self-hosted VPN journey on.
You can help keep my site up and running by checking out the VPS providers that I use via the Affiliate links over on the left hand side there!
A Quick Introduction to OpenVPN
OpenVPN is a popular open-source VPN (Virtual Private Network) solution known for its security, flexibility, and cross-platform compatibility with apps for iOS, Android, Windows, and Mac OSX.
In this guide, we will walk you through the process of setting up an OpenVPN server on Debian 11.
Setting Up The Server
This guide assumes you have a freshly installed or deployed image of Debian 11. Debian 12 was released a couple of weeks before writing this post, however not all VPS providers will provide images of Debian 12 straight away, so we’ll stick with Debian 11 for this post.
Step 1: Preparing the server
Before we start, we’ll ensure your Debian 11 system is up to date. Login as root on your server, and run the following commands (if you don’t have root access, you probably have sudo. Prepend these commands with sudo):
apt update
apt dist-upgrade
We’ll also install a few handy utilities to help us set up our server
- iftop allows us to check our bandwidth usage in realtime
- iptables-persistent will allow us to save and restore iptables (linux’s built in firewall) rules
apt install iftop iptables-persistent
If we are assuming that this is running on a VPS, we need to make sure that we secure the server as a priority to make sure it doesn’t get compromised!
The following commands will set up the firewall to block any incoming connections from the internet except for OpenVPN, but allow incoming connections if you’ve initiated the connection. We will also set up the masquerade rule that we will need to allow VPN traffic to be routed out of the VPN server to the internet.
Replace eth0 in this code block if your VPS uses a different interface for it’s internet facing interface.
IF YOU’RE DOING THIS OVER SSH ON A VPS, THE FIRST LINE WILL LOCK YOU OUT.
DO NOT RUN THE FIRST LINE YET.
iptables -P INPUT DROP
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT-i eth0 -p udp --dport 1194 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.100.100.0/24 -o eth0 -j MASQUERADE
iptables-save > /etc/iptables/rules.v4
If you’re going to be SSH-ing to this server without the VPN, then it’s also recommended to set up certificate based authentication, however in this post, we will assume that any remote access will be via the VPN after it is set up.
Next is to enable routing on the server so that we can route our internet through our VPN. We do this by modifying the /etc/sysctl.conf
file to enable IP Forwarding, and then updating the system via sysctl
.
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
sysctl -p
Step 2: Installing and setting up the supporting infrastructure.
Now to install OpenVPN and set up all the certificates that go along with OpenVPN. We can do that with a simple apt command like so:
apt install openvpn
After OpenVPN has been installed, we’ll need to generate the server certificates and keys that OpenVPN will use for authentication. When we install OpenVPN, Easy-RSA is also installed as a dependency, which is what we’ll be using to generate the necessary certificates and keys.
Run the following commands to create a directory to keep your Certificate Authority in. Feel free to use an alternate path to what I’ve written, I just like to keep my server organised:
make-cadir /opt/openvpn-ca
cd /opt/openvpn-ca
We’ll need to modify the vars file to suit our setup. Open the vars file with the following command
nano vars
Then we find the following lines, uncomment them, and modify them to suit.
set_var EASYRSA_DN "org"
set_var EASYRSA_REQ_COUNTRY "Your Country"
set_var EASYRSA_REQ_PROVINCE "Your Province"
set_var EASYRSA_REQ_CITY "Your City"
set_var EASYRSA_REQ_ORG "Your Organization"
set_var EASYRSA_REQ_EMAIL "Your Email"
set_var EASYRSA_REQ_OU "Your OU"
Save(CTRL-O) the file once you’ve finished modifying it, and exit(CTRL-X) nano.
Next we generate the PKI (Public Key Infrastructure) and a CA (Certificate Authority)
./easyrsa init-pki
./easyrsa build-ca
You will be asked for a CA Key passphrase at this point, create one and MAKE SURE YOU WRITE IT DOWN.
After that, you will be required to fill in the hostname of your server.
Next up is to create the server certificate – the nopass at the end is important so that your OpenVPN server can start without requiring a password input. The command will also ask for a pass phrase for the key, use the one you just wrote down. Replace SERVERNAME
with your server’s host name. This will also be the name of your certificates and keys.
./easyrsa build-server-full SERVERNAME nopass
And then we need to create a client certificate for use on our VPN Clients. Again, replace CLIENTNAME
with a descriptive name for your client certificates, especially if you will have more than one device connecting.
./easyrsa build-client-full CLIENTNAME
The command will request a PEM pass phrase, create one and WRITE IT DOWN. It will also request for the CA Key passphrase.
To enhance the security of the VPN connection, we will also generate a Diffie-Hellman key exchange with the following command:
./build-dh
The result will be stored in the root of the PKI (/opt/openvpn-ca/pki/dh.pem
if you have been following along with me) – take a note of the location if you have stored it elsewhere.
Step 3: Setting up OpenVPN
Phew. After all that, we’re finally getting to the bit where we actually set up OpenVPN.
First up, we’ll generate an HMAC signature to harden our OpenVPN Server.
To do that, we’ll change our current directory to the openvpn configuration directory, and then generate the key with the following commands:
cd /etc/openvpn
mkdir keys
openvpn --genkey secret keys/ta.key
After that is done, we can now start configuring our OpenVPN server. Create a configuration file –
nano /etc/openvpn/server.conf
and then paste the following configuration into the file
If you have moved any of the certificates or keys, make sure you update the locations below.
port 1194 proto udp dev tun ca /opt/openvpn-ca/pki/ca.crt #UPDATE THIS IF REQUIRED cert /opt/openvpn-ca/pki/issued/server.crt #UPDATE THIS IF REQUIRED key /opt/openvpn-ca/pki/private/server.key #UPDATE THIS IF REQUIRED dh /opt/openvpn-ca/pki/dh.pem topology subnet server 10.100.100.0 255.255.255.0 # UPDATE THIS IF YOUR NETWORK WILL CONFLICT ifconfig-pool-persist ipp.txt push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 1.1.1.1" push "dhcp-option DNS 1.0.0.1" keepalive 10 120 tls-auth /etc/openvpn/keys/ta.key 0 data-ciphers AES-256-CBC:AES-256-GCM:AES-128-GCM data-ciphers-fallback AES-256-CBC comp-lzo user nobody group nogroup persist-key persist-tun status /var/log/openvpn/status.log verb 3
Save (CTRL-O) and close (CTRL-X) the file.
Now we can start and enable the OpenVPN Service to ensure it runs automatically on system boot:
sudo systemctl start openvpn@server
sudo systemctl enable openvpn@server
Last step is to allow incoming traffic from the OpenVPN interface to hit the server. This allows things like SSH to access the server from the VPN.
iptables -A INPUT -i tun0 -j ACCEPT
iptables-save > /etc/iptables/rules.v4
Step 4: Setting up the client
Woooo. Still with me there? Goodo. Next up is to set up a client.
To do this, we will need the following files from the server.
/opt/openvpn-ca/pki/ca.crt
/opt/openvpn-ca/pki/private/client.key # FILENAME MAY DIFFER
/opt/openvpn-ca/pki/issued/client.crt # FILENAME MAY DIFFER
/etc/openvpn/keys/ta.key
Copy all of those files to your client device. If you have set a default block policy on your VPS, you can temporarily allow SSH with the following command:
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
Once you have downloaded the files, you can remove this rule with the following command
iptables -D INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
Create a client.ovpn file and copy the following lines into it – replace YOUR-SERVER-IP
with the internet facing IP address of your server.
client
dev tun
proto udp
remote YOUR-SERVER-IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
block-outside-dns
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
comp-lzo
verb 3
Once that is done, save the file on the client, and import the configuration into your OpenVPN Client.
If you’re doing this via SSH on a VPS, don’t forget to set the default policy on the firewall to block incoming with the following iptable commands!
iptables -P INPUT DROP && iptables-save > /etc/iptables/rules.v4
Congratulations! You have successfully set up an OpenVPN server on Debian 11. With this VPN server, you can now securely access your private network from remote locations, or route your traffic out of your very own VPN Server. Enjoy the benefits of a secure and private connection with OpenVPN!