Installing OpenVPN Server on Debian 12 from [A to Z]

Man

Professional
Messages
2,965
Reaction score
488
Points
83
A Virtual Private Network (VPN) allows you to access the internet while hiding your location, giving you the freedom to securely access the internet on untrusted networks and bypass geo-restrictions and censorship. OpenVPN is an open-source Transport Layer Security (TLS) VPN solution to achieve this.

In this tutorial, we will install OpenVPN on a Debian 12 server and configure it to be accessible from a client machine, as well as create a VPN connection between the two to route all traffic from the client through the OpenVPN server.

Requirements

- A server running Debian 12 that supports both IPv4 and IPv6 connections. We will refer to this as the OpenVPN server. It has a simple firewall (UFW) enabled and running.

- A server running Debian 12 that supports both IPv4 and IPv6 connections. We will configure this as a private Certificate Authority (CA), which we will refer to as the CA server.

- A non-root user with sudo privileges on both OpenVPN and the CA server

. - A client machine to connect to the OpenVPN server. You can use a local device as a client machine. OpenVPN has clients for Windows, Linux, macOS, Android, and iOS. You can use any of them to connect. For the purposes of this tutorial, we will be using a Debian 12 client PC.

- Everything up to date on OpenVPN and the CA server.

# update repositories
apt update
# update the system
apt upgrade
# install sudo for convenience
apt install sudo

[Step 1 — Setting Up the CA Server]


A Certificate Authority (CA) is an organization responsible for issuing digital certificates to verify identities online. In this tutorial, we will be using a standalone server as a private CA server that will verify the OpenVPN server and client certificates. Your CA server should not run any other services other than importing, signing, and verifying certificates.

Step 1.1 — Installing Easy-RSA

The first step is to install the easy-rsa script suite. Easy-rsa is a CA management tool used to generate private key and public root certificate.

# install tools
sudo apt install easy-rsa -y

Step 1.2 — Create Public Key Infrastructure Directory


The next step is to create a public key infrastructure (PKI) skeleton on the CA server.

# create directory
mkdir /root/easy-rsa

Create symbolic links pointing to the installed easy-rsa package files.

# create symbolic link
ln -s /usr/share/easy-rsa/* /root/easy-rsa/

Restrict access to the PKI directory.

# change permissions to 700
chmod 700 /root/easy-rsa/

Initialize the PKI.

# change to the desired directory
cd /root/easy-rsa
# initialize pki
./easyrsa init-pki

You will get the following output.

* Notice:

init-pki complete; you may now create a CA or requests.

Your newly created PKI dir is:
* /root/easy-rsa/pki

* Notice:
IMPORTANT: Easy-RSA 'vars' file has now been moved to your PKI above.

Step 1.3 — Create a Certificate Authority


Before you can create your CA's private key and certificate, you need to configure the organization information for it. The vars configuration file has already been created in the pki directory. Open it for editing.

# change to the desired directory
cd /root/easy-rsa
# edit the variables
nano pki/vars

Find the following variables and uncomment them by removing the hash (#) character in front of them and editing them as shown below.

set_var EASYRSA_REQ_COUNTRY "RU"
set_var EASYRSA_REQ_PROVINCE "Rostovskaya Oblast"
set_var EASYRSA_REQ_CITY "Rostov-on-Don"
set_var EASYRSA_REQ_ORG "xss.is"
set_var EASYRSA_REQ_EMAIL " yasha@xss.is "
set_var EASYRSA_REQ_OU "Community"
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"


Save the file by pressing F2 and entering Y when prompted.

Run the following command to generate a root public and private key pair for your CA.

# build ca
./easyrsa build-ca

You will be prompted to enter a passphrase for your key pair. Choose a strong passphrase and remember it for future reference. Next, you will be prompted to enter a PEM passphrase. You will also be prompted to provide a common name (CN) for your CA. You can enter any string, but for simplicity, press ENTER to accept the default name.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)


Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
Using configuration from /root/easy-rsa/pki/0317a4e9/temp.7598e8cc
Enter PEM pass phrase:
802B61D1317F0000:error:14000065:UI routines:UI_set_result_ex:result too small:../crypto/ui/ui_lib.c:888:You must type in 4 to 1024 characters
802B61D1317F0000:error:1400006B:UI routines:UI_process :processing error:../crypto/ui/ui_lib.c:548:while reading strings
802B61D1317F0000:error:0480006D :pEM routines :pEM_def_callback:problems getting password:../crypto/pem/pem_lib.c:62:
802B61D1317F0000:error:07880109:common libcrypto routines:do_ui_passphrase:interrupted or cancelled:../crypto/passphrase.c:184:
802B61D1317F0000:error:1C80009F :provider routines :p8info_to_encp8:unable to get passphrase:../providers/implementations/encode_decode/encode_key2any.c:116:

Easy-RSA error:

Failed to build the CA

Host: nix | Linux | /bin/bash


If you don't want to be prompted for your password every time you interact with your CA, you can use the following command.

# disable password
/root/easy-rsa/easyrsa build-ca nopass

This will create two files:

/root/easy-rsa/pki/ca.crt - This is the CA's public certificate file. Every OpenVPN user and server will need a copy of this file.
/root/easy-rsa/pki/private/ca.key - This is the private key used by the CA to sign certificates for the OpenVPN server and client. If an attacker gains access to your CA, and in turn your ca.key file, you will need to destroy your CA. This is why your ca.key file should only reside on your CA machine, and ideally your CA machine should be offline when not signing certificate requests, as an added security measure.

[Step 2 - Install OpenVPN and Easy-RSA on the OpenVPN Server]

Log in to your OpenVPN server and install the OpenVPN and Easy-RSA packages.

# update repositories
apt update
# update the system
apt upgrade
# install sudo for convenience
apt install sudo
# install openvpn and rsa
sudo apt install openvpn easy-rsa -y

Create the directory /root/easy-rsa.

# create the directory for rsa
mkdir /root/easy-rsa

Create a symbolic link from the easy-rsa script that we installed, just like on the CA server.

# make the symbolic link
ln -s /usr/share/easy-rsa/* /root/easy-rsa/

Restrict access to the directory.

# change the permissions to 700
chmod 700 /root/easy-rsa

Step 3 - Create a PKI for the OpenVPN server

The next step is to create the PKI directory using the init-pki option. Although you already ran this command on the CA server as part of the prerequisites, you need to run it here because your OpenVPN server and CA server have separate PKI directories.

# go to the desired directory
cd /root/easy-rsa
# initialize the PKI
./easyrsa init-pki

PKI on the OpenVPN server is used as a centralized place to store certificate requests and public certificates.

Open the /root/easy-rsa/pki/vars directory to store the information needed to create the PKI and open it for editing.

# edit variables
nano pki/vars

Find the following variables and uncomment them by removing the hash sign (#) in front of them and change their values as shown below.

->
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"

->

Save the file by pressing F2 and entering Y when prompted.

Since we are not using this server as a CA, these are the only values we need. This configures your OpenVPN and CA servers to use ECC, which means that when the client and server try to establish a shared symmetric key, they use elliptic curve algorithms to exchange. This is significantly faster than using plain Diffie-Hellman with the classic RSA algorithm, as the numbers are much smaller and the calculations are faster.

[Step 4 – Generate OpenVPN Server Certificate Request and Private Key]

Navigate to the /root/easy-rsa/ directory on your OpenVPN server.

# cd to the directory you want
cd /root/easy-rsa

The next step is to generate a private key and certificate signing request (CSR) on your OpenVPN server. Run the easy-rsa command with the gen-req option followed by the common name (CN) for the server. For our tutorial, we will use server as the CN for the OpenVPN server. We will also use the nopass option to avoid permission issues.

# make the request
./easyrsa gen-req server nopass

You will get the following output.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)

-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [server]:
* Notice:

Keypair and certificate request completed. Your files are:
req: /root/easy-rsa/pki/reqs/server.req
key: /root/easy-rsa/pki/private/server.key


This will create a private key for the server and a certificate request file named server.req. Copy the server key to the /etc/openvpn/server directory.

# copy the private key
sudo cp /root/easy-rsa/pki/private/server.key /etc/openvpn/server/

The Certificate Signing Request (CSR) is now ready to be signed by the CA.

[Step 5 – Signing the OpenVPN Server CSR]

The next step is to copy the CSR file to the CA server for signing. If you have password authentication enabled on your servers, you can simply use the following command to copy the file.

# copy file to server 1.1.1.1
scp /root/easy-rsa/pki/reqs/server.req root@1.1.1.1 :/tmp

If you don’t want to use password authentication, you’ll need to generate an SSH key pair for each server and then add the OpenVPN server’s public SSH key to the CA machine’s authorized_keys file and vice versa.

If you don’t want to go through all that trouble, you can simply copy the files. Open the file on the OpenVPN server, copy its contents, and then create a file on the CA server and paste the contents.

Log in to CA Server again, go to the /root/easy-rsa directory and import the CSR file.

# change to the correct directory
cd /root/easy-rsa
# import the request
./easyrsa import-req /tmp/server.req server

You will get the following output.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)

* Notice:

The request has been successfully imported with a short name of: server
You may now use this name to perform signing operations on this request.


Sign the request with the following command. Since we are signing the OpenVPN server's CSR, we will use its Common Name (CN).

# sign
./easyrsa sign-req server server

You will be prompted to verify that the request is from a trusted source. Type yes and press ENTER to confirm.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=
commonName = server


Type the word 'yes' to continue, or any other input to abort.
Confirm request details:


Next, you will be prompted to enter the CA private key passphrase you set up earlier

Using configuration from /root/easy-rsa/pki/787c6c48/temp.ee62a106
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'server'
Certificate is to be certified until Apr 10 16:49:09 2027 GMT (825 days)

Write out database with 1 new entries
Database updated

* Notice:
Certificate created at: /root/easy-rsa/pki/issued/server.crt


The received certificate contains the OpenVPN server's public encryption key as well as the server's CA signature. Copy the certificates back to the OpenVPN server.

# copy the files back to the vpn server
scp pki/issued/server.crt root@8.8.8.8 :/tmp
scp pki/ca.crt root@8.8.8.8 :/tmp


On your OpenVPN server, copy the files to the /etc/openvpn/server directory.

# copy the files to the openvpn directory
sudo cp /tmp/{server.crt,ca.crt} /etc/openvpn/server

[Step 6 — Configure OpenVPN Cryptography]


We will add an additional shared secret that the server and all clients will use with OpenVPN's tls-crypt directive. This ensures that the OpenVPN server can cope with unauthenticated traffic, port scans, and denial of service attacks. It will also make it more difficult to identify OpenVPN network traffic.

Change to the /root/easy-rsa directory.

# change to the desired directory
cd /root/easy-rsa

Create a strong Diffie-Hellman key to use during the key exchange using the following command.

# create the DH key
./easyrsa gen-dh

Generate a pre-shared tls-crypt key. This will create a file named ta.key

# generate the key
sudo openvpn --genkey secret ta.key

Copy ta.key to the /etc/openvpn/server directory.

# copy the keys to the openvpn directory
sudo cp ta.key /etc/openvpn/server
sudo cp pki/dh.pem /etc/openvpn/server

[Step 7 — Generate the Client Certificate and Key Pair]


Create a directory on your VPN server to store the client certificate and key files.

# create a directory for the keys
mkdir -p /root/client-configs/keys

Restrict the permissions on the directory to protect it.

# change permissions to 700
chmod -R 700 /root/client-configs

Then switch to the /root/easy-rsa directory.

# go to the directory
cd /root/easy-rsa

Generate a client key client1 with a Common Name for the client. You can use any CN for the client.

# generate a client key
./easyrsa gen-req client1 nopass

Press ENTER to confirm the Common Name. You will get the following output.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)

-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [client1]:
* Notice:

Keypair and certificate request completed. Your files are:
req: /root/easy-rsa/pki/reqs/client1.req
key: /root/easy-rsa/pki/private/client1.key


Next, copy the client1.key file to the /root/client- directory. configs/keys.

# copy the key to the clients folder
cp pki/private/client1.key /root/client-configs/keys/

Upload the client1.req file to the CA server.

# copy the file to the 1.1.1.1 server
scp pki/reqs/client1 .req root@1.1.1.1 :/tmp

Login to the CA server again and import the server request.

# go to the directory
cd /root/easy-rsa
# Import the request
./easyrsa import-req /tmp/client1.req client1

You will get the following result.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)

* Notice:

The request has been successfully imported with a short name of: client1
You may now use this name to perform signing operations on this request.


Sign the request using the following command. We use client as the request type.

# sign
./easyrsa sign-req client client1

When prompted, click yes to confirm signing the request and ensure that it comes from a trusted source.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a client certificate for 825 days:

subject=
commonName = client1


Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes


You will be prompted to enter your CA passphrase.

Using configuration from /root/easy-rsa/pki/8d3a02ae/temp.53b43101
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'client1'
Certificate is to be certified until Apr 10 17:09:50 2027 GMT (825 days)

Write out database with 1 new entries
Database updated

* Notice:
Certificate created at: /root/easy-rsa/pki/issued/client1.crt


Transfer the created certificate back to the OpenVPN server.

# copy back to vpn server
scp pki/issued/client1.crt root@8.8.8.8 :/tmp

On OpenVPN server copy client certificate to /root/client-configs/keys directory.

# copy certificate
cp /tmp/client1.crt / root/client-configs/keys/

Copy the ca.crt and ta.key files to the /root/client-configs/keys directory and set the appropriate permissions for your current server.

# copy files
sudo cp /root/easy-rsa/ta.key /root/client-configs/keys/
# copy files
sudo cp /etc/openvpn/server/ca.crt /root/client-configs/keys/
# change sudo
chown root:root /root/client-configs/keys/*

[Step 8 - Configure OpenVPN]


Copy the sample server.conf file as a starting point for configuring OpenVPN.

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

Open the file for editing.

# open for editing
sudo nano /etc/openvpn/server/server.conf

Find the HMAC section of the file, finding the tls- directive auth. Comment out the line by adding a semicolon (;)at the beginning of the line. Add a new line below it as shown.

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


Next, change the cryptographic cipher value by finding the cipher lines. Value by default it is set to AES-256-CBC. Comment out the default value and add another line with AES-256-GCM encryption, which provides better encryption and performance, as shown.

;cipher AES-256-CBC
cipher AES-256- GCM


Below add the auth directive to select the HMAC message digest algorithm.

auth SHA256

Since we are using Elliptic Curve Encryption, we need to disable Diffie-Hellman encryption. Comment out the dh dh2048.pem line and add dh none below it.

;dh dh2048.pem
dh none


OpenVPN should run without privileges after startup. To enable this, find and uncomment the ;user openvpn and ;group openvpn lines and change them as shown.

user nobody
group nogroup


Redirect all traffic through VPN

The settings above create a VPN connection between the client and server, but do not force any connections to use the tunnel. To do this, start by looking for the line "redirect-gateway def1 bypass-dhcp". This line tells the client to redirect all its traffic through the OpenVPN server. Uncomment the line to enable this functionality.

push "redirect-gateway def1 bypass-dhcp"

Find the dhcp-option section below this line. Remove the semicolon from the beginning of both lines. This tells the client to use the OpenDNS resolvers.

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


Change Port and Protocol

OpenVPN uses port 1194 and the UDP protocol by default to accept client connections. You can change the port depending on your needs. If you are not hosting web content on your OpenVPN server, you can use port 4433.

Find the line port 1194 and change its value.

# Optional!
port 4433


Find the line proto udp line and comment it out by adding a semicolon in front of it. And uncomment the line proto tcp by removing the semicolon as shown.

proto tcp
;proto udp


Since we are using the TCP protocol, we need to change the explicit-exit-notify directive value from 1 to 0, since this directive is used only by UDP.

explicit-exit-notify 0

Specify Non-Default Credentials

If you chose a different name during the ./easy-rsa gen-req server command earlier, you will need to change the cert and key lines to point to the appropriate .crt and .key files. Since we are using the default server name, the default value is correct.

cert server.crt
key server.key


Once finished, save the file by pressing F2 and entering Y when prompted.

[Step 9 – Configure OpenVPN Server Networking]

The next step is to configure the server networking configuration so that OpenVPN can route traffic correctly. The first thing we need to configure is port forwarding.

Open the /etc/sysctl.conf file for editing.

# open for editing
sudo nano /etc/sysctl.conf

Add the following line to the end of the file.

net.ipv4.ip_forward = 1

Save the file by pressing F2 and entering Y when prompted.

To read the file and load the new values for the current session, use the following command.

# reread
sudo sysctl -p

This configuration will route all web traffic from your client through your server's IP address, and your client's public IP address will effectively be hidden.

[Step 10 - Configure the Firewall]

To allow OpenVPN to pass through the firewall, you need to enable masquerading, a concept in iptables that provides dynamic, on-the-fly Network Address Translation (NAT) to route client connections correctly.

Before you open the firewall configuration file to add masquerading rules, first find the public network interface of your computer using the following command.

# look at the route
ip route list default

You will get a similar result.

default via 10.0.0.1 dev ens3 onlink

This tells us that the interface name is ens3. Open the /etc/ufw/before.rules file for editing.

# install firefox first
sudo apt install ufw -y
# open the rules for editing
sudo nano /etc/ufw/before.rules

These rules are read and applied before the regular UFW rules are loaded. Add the following lines to the top of the file as shown.

*nat
:pOSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/8 -o ens3 -j MASQUERADE
COMMIT


Save the file by pressing F2 and entering Y when prompted.

Next, we need to configure UFW to allow forwarded packets by default. Open the /etc/default/ufw file for editing.

# open the rules for editing
sudo nano /etc/default/ufw

Find the DEFAULT_FORWARD_POLICY directive and change its value from DROP to ACCEPT.

DEFAULT_FORWARD_POLICY="ACCEPT"

Save the file by pressing F2 and entering Y when prompted.

Finally, open port 4433 that you previously configured for the OpenVPN server.

sudo ufw allow 22/tcp
sudo ufw allow 4433/tcp


Disable and then enable the firewall to apply the new configuration.

sudo ufw disable
sudo ufw enable

[Step 11 - Start OpenVPN]


Start the OpenVPN service.

# start
sudo systemctl start openvpn-server@server.service

Check the service status.

# view status
sudo systemctl status openvpn-server@server.service

You should get a similar result.

openvpn-server@server.service - OpenVPN service for server
Loaded: loaded (/lib/systemd/system/ openvpn-server@.service ; disabled; preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Mon 2025-01-06 11:02: 39 MSK; 175ms ago
Docs: man :eek:penvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Process: 7295 ExecStart=/usr/sbin/openvpn --status /run/openvpn-server/status-server.log --status-version 2 --suppress-timestamps --conf>
Main PID: 7295 (code=exited, status=1/FAILURE)
Status: "Pre- connection initialization successful"
CPU: 35ms


Enable the OpenVPN service to start at boot.

# add to vpn autostart
sudo systemctl -f enable openvpn-server@server.service

[Step 12 - Create a client configuration]


Before testing the client, we need to create configuration files for the client, which we will use. Create a directory to store client configuration files.

# create a folder for client configs
mkdir -p /root/client-configs/files

Copy the sample client configuration file to the directory.

# copy the sample config
cp /usr/share/doc/openvpn/examples/sample -config-files/client.conf /root/client-configs/base.conf

Open the configuration file for editing.

# edit the file
nano /root/client-configs/base.conf

Find the remote directive and set it to point to public IP address of your OpenVPN server. Also change the port to match the port you selected earlier.

#
remote server ip 8.8.8.8 4433

Set the protocol you selected earlier by uncommenting it and commenting out the proto udp setting.

# server port
proto tcp

Uncomment the user and group, removing the semicolon in front of them. Also change the values as follows.

# permissions
user nobody
group nogroup


Find the ca, cert, and key directives and comment them out by putting a semicolon in front of them. This is because we will add the certificates and keys to the client configuration file.

#
;ca ca.crt
;cert client.crt
; key client.key


Comment out the tls-auth directive as we will add ta.key directly to the client config file.

#
;tls-auth ta.key 1

Match the cipher setting you set in "/etc/openvpn/server/server .conf". Also add the auth setting to the end of the file.

cipher AES-256-GCM
auth SHA256


Add the key-direction directive and set it to 1 for the VPN to work correctly.

key-direction 1

Next, add some commented lines to handle the different methods used by VPN clients for DNS resolution. Add the following set of lines for clients that do not use systemd-resolved but rely on the resolvconf utility to manage DNS.

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


Add the following set of lines for clients that do use systemd-resolved DNS resolution.

; script-security 2
; up /etc/openvpn/update-systemd-resolved
; down /etc/openvpn/update-systemd-resolved
; down-pre
; dhcp-option DOMAIN-ROUTE .


Save the file by pressing F2 and entering Y when prompted.

Create a script to compile a base configuration with the appropriate certificate, key, and encryption files, then copy the generated configuration file to the /root/client-configs/files directory.

Create and open the make_config.sh file in the /root/client-configs directory.

# edit the
nano file /root/client-configs/make_config.sh
Paste the following code into it.

#!/bin/bash

KEY_DIR=/root/client-configs/keys
OUTPUT_DIR=/root/client-configs/files
BASE_CONFIG=/root/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-crypt>') \
${KEY_DIR}/ta.key \
<(echo -e '</tls-crypt>') \
> ${OUTPUT_DIR}/${1}.ovpn


Save the file by pressing F2 and entering Y when prompted.

Make the file executable and restrict its permissions.

# Change permissions
chmod 700 /root/client-configs/make_config.sh

This script makes a copy of the base.conf file, collects all the certificate and key files, extracts their contents, adds them to the base config file, and exports it all to create a new client configuration file. Each time you add a new client, you need to generate new keys and certificates for it, and then run this script to create the client configuration file.

We already created the client certificate and key files in step 7. Let's create a config file for them.

Change to the /root/client-configs directory.

# go to the desired directory
cd /root/client-configs

Run the script to create the client configuration file.

# run the
./make_config script.sh client1

This will create a file called client1.ovpn. Change the parameter if you want a different file name. Check the contents of the directory.

# view files
ls /root/client-configs/file s

This is the configuration file that you need to transfer to the client, which will then be used to connect to the OpenVPN server. You can use any SFTP protocol/program to transfer the file to the client.

[Step 13 - Setting up and testing the client connection]
For our tutorial, we are using a Debian 12 client machine. Install OpenVPN using the following command.

# update repositories
apt update
# update the system
apt upgrade
# install sudo for convenience
apt install sudo
# install vpn on the client
sudo apt install openvpn -y

Check if your system is using systemd-resolved to manage DNS queries by running the following command.

# view dns
cat /etc/resolv.conf

If the system is using systemd-resolved, then the IP address above will be 127.0.0.53. Also, the comment at the top of the file will confirm the same. If the IP address is different from 127.0.0.53, then the system is not using systemd-resolved and you need to follow the steps given below.

But first, download the client1.ovpn file from the server using the following command.

# copy the file from the server to your client
scp root@8.8.8.8 :/root/client-configs/files/client1.ovpn /tmp
===
For clients with systemd-resolved

Install the openvpn-systemd-resolved package which contains scripts that force the use of systemd-resolved VPN server for DNS.

# install the packages
sudo apt install openvpn-systemd-resolved -y

Open the client configuration file for editing.

# edit
nano /tmp/client1.ovpn

Uncomment the following lines in the file by deleting the semicolon in front of them.

script-security 2
up /etc/openvpn/update-systemd-resolved
down /etc/openvpn/update-systemd-resolved
down-pre
dhcp-option DOMAIN-ROUTE .


Save the file by pressing F2 and entering Y when prompted.
===
For clients with update-resolv-conf

This is the step you need to use if you have a Debian system. First, make sure your distribution uses update-resolv-conf.

# look at files
ls /etc/openvpn
If your system has this update-resolv-conf file, open the client configuration file for editing.

# edit again
nano /tmp/client1.ovpn
Uncomment the following lines in the file by removing the semicolon in front of them.

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


If you are using a CentOS-based distribution, change the group directive from nogroup to nobody.

group nobody

Save the file by pressing F2 and entering Y when prompted.

Connecting the Client

Run the following command to connect the client to the VPN server.

sudo openvpn --config /tmp/client1.ovpn

2023-08-08 16:23:29 Note: Kernel support for ovpn-dco missing, disabling data channel offload.
2023-08-08 16:23:29 OpenVPN 2.6.3 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]
2023-08-08 16:23:29 library versions: OpenSSL 3.0.9 30 May 2023, LZO 2.10
2023-08-08 16:23:29 DCO version: N/A
2023-08-08 16:23:29 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
2023-08-08 16:23:29 TCP/UDP: Preserving recently used remote address: [AF_INET]69.28.91.204:443
2023-08-08 16:23:29 Socket Buffers: R=[131072->131072] S=[16384->16384]
2023-08-08 16:23:29 Attempting to establish TCP connection with [AF_INET]69.28.91.204:443
2023-08-08 16:23:29 TCP connection established with [AF_INET]69.28.91.204:443
2023-08-08 16:23:29 TCPv4_CLIENT link local: (not bound)
2023-08-08 16:23:29 TCPv4_CLIENT link remote: [AF_INET]69.28.91.204:443
2023-08-08 16:23:29 NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay
2023-08-08 16:23:29 TLS: Initial packet from [AF_INET]69.28.91.204:443, sid=6bd67e12 50ebf8bc
2023-08-08 16:23:30 VERIFY OK: depth=1, CN=Easy-RSA CA
2023-08-08 16:23:30 VERIFY KU OK
2023-08-08 16:23:30 Validating certificate extended key usage
2023-08-08 16:23:30 ++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
2023-08-08 16:23:30 VERIFY EKU OK
2023-08-08 16:23:30 VERIFY OK: depth=0, CN=server
2023-08-08 16:23:30 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 384 bit ECsecp384r1, signature: ecdsa-with-SHA512
2023-08-08 16:23:30 [server] Peer Connection Initiated with [AF_INET]69.28.91.204:443
2023-08-08 16:23:30 TLS: move_session: dest=TM_ACTIVE src=TM_INITIAL reinit_src=1
2023-08-08 16:23:30 TLS: tls_multi_process: initial untrusted session promoted to trusted
2023-08-08 16:23:31 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1)
2023-08-08 16:23:31 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,route 10.8.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM,protocol-flags cc-exit tls-ekm dyn-tls-crypt,tun-mtu 1500'
2023-08-08 16:23:31 OPTIONS IMPORT: --ifconfig/up options modified
2023-08-08 16:23:31 OPTIONS IMPORT: route options modified
2023-08-08 16:23:31 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
2023-08-08 16:23:31 OPTIONS IMPORT: tun-mtu set to 1500
2023-08-08 16:23:31 net_route_v4_best_gw query: dst 0.0.0.0
2023-08-08 16:23:31 net_route_v4_best_gw result: via 10.0.2.2 dev enp0s3
2023-08-08 16:23:31 ROUTE_GATEWAY 10.0.2.2/255.255.255.0 IFACE=enp0s3 HWADDR=08:00:27:b7:cc:29
2023-08-08 16:23:31 TUN/TAP device tun0 opened
2023-08-08 16:23:31 net_iface_mtu_set: mtu 1500 for tun0
2023-08-08 16:23:31 net_iface_up: set tun0 up
2023-08-08 16:23:31 net_addr_ptp_v4_add: 10.8.0.6 peer 10.8.0.5 dev tun0
2023-08-08 16:23:31 /etc/openvpn/update-resolv-conf tun0 1500 0 10.8.0.6 10.8.0.5 init
2023-08-08 16:23:31 net_route_v4_add: 69.28.91.204/32 via 10.0.2.2 dev [NULL] table 0 metric -1
2023-08-08 16:23:31 net_route_v4_add: 0.0.0.0/1 via 10.8.0.5 dev [NULL] table 0 metric -1
2023-08-08 16:23:31 net_route_v4_add: 128.0.0.0/1 via 10.8. 0.5 dev [NULL] table 0 metric -1
2023-08-08 16:23:31 net_route_v4_add: 10.8.0.1/32 via 10.8.0.5 dev [NULL] table 0 metric -1
2023-08-08 16:23:31 UID set to nobody
2023-08- 08 16:23:31 GID set to nogroup
2023-08-08 16:23:31 Capabilities retained: CAP_NET_ADMIN
2023-08-08 16:23:31 Initialization Sequence Completed
2023-08-08 16:23:31 Data Channel: cipher 'AES-256-GCM', peer-id: 0
2023-08-08 16:23:31 Timers: ping 10, ping-restart 120
2023-08-08 16:23:31 Protocol options: protocol-flags cc-exit tls-ekm dyn-tls-crypt


You can check the connection by running curl ident.me in your browser, and you will see your IP address and the location of your OpenVPN server.

# install curl
apt install curl -y
# make a request to the server
curl ident.me

You can check the site for IP leaks here - https://www.dnsleaktest.com/

The above command starts OpenVPN in the foreground, which means that the terminal will be locked. To close the connection, you need to press Ctrl + C. However, you can also start OpenVPN in the background. Use the following command to do so.

# start in the background
sudo openvpn --config client1.ovpn --daemon

To terminate the connection, find the process ID.

# finding the process
ps aux | grep openvpn

nobody 1819 0.1 0.3 13316 7860 ? Ss 16:18 0:00 openvpn --config /tmp/client1.ovpn --daemon
root 1833 0.0 0.1 6332 2144 pts/0 S+ 16:18 0:00 grep openvpn

As you can see, the process ID corresponding to the OpenVPN process is 1819. Terminate the VPN connection with the following command to kill the process.

# terminating the process
sudo kill -9 1819

OpenVPN offers graphical clients for Windows, macOS, Android, and iOS platforms, where you can import the client configuration file to connect.

[Step 14 - Revoke Client Certificates]

If you want to revoke a client certificate to prevent access, you can do so by logging into the CA server

. Go to the /root/easy-rsa directory.

# go to the desired directory
cd /root/easy-rsa

Run the script with the revoke option followed by the client name.

# revoke the client
./easyrsa revoke client1

You will be prompted to revoke the certificate.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)


Please confirm you wish to revoke the certificate
with the following subject:

subject=
commonName = client1

serial-number: 940E2BF50BA5C75649EF18F7969FDE4A



Type the word 'yes' to continue, or any other input to abort.
Continue with revocation: yes

If your CA private key is passphrase-protected, enter the passphrase when prompted.

Using configuration from /root/easy-rsa/pki/2f7d3491/temp.36ca6058
Revoking Certificate 940E2BF50BA5C75649EF18F7969FDE4A.
Database updated

* Notice:

IMPORTANT!!!

Revocation was successful. You must run gen-crl and upload a CRL to your
infrastructure in order to prevent the revoked cert from being accepted.


This revokes the certificate on the CA server. However, the OpenVPN server has no way to check the revocation status. To do this, we need to generate a Certificate Revocation List (CRL) and upload it to the OpenVPN server.

Generate a CRL.

# generate for revocation
./easyrsa gen-crl

You will be prompted for the CA passphrase. The above command generates the crl.pem file.

* Notice:
Using Easy-RSA configuration from: /root/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)

Using configuration from /root/easy-rsa/pki/e39ca1a2/temp.e63e54d4

* Notice:

An updated CRL has been created.
CRL file: /root/easy-rsa/pki/crl.pem


Copy this file to the OpenVPN server.

# copy the CRL to the server
scp /root/easy-rsa/pki/crl.pem root@8.8.8.8 :/tmp
Log in to the OpenVPN server again and copy the CRL file to the /etc/openvpn/server directory.

# copy the CRL to the folder
sudo cp /tmp/crl.pem /etc/openvpn/server/

Open the OpenVPN server configuration file for editing.

# open for editing
sudo nano /etc/openvpn/server/server.conf

Add the following line to the end of the file. This instructs the OpenVPN server to check the revocation list for clients that have been restricted.

crl-verify crl.pem

Save the file by pressing F2 and entering Y when prompted.

Restart the OpenVPN server for the changes to take effect.

# restart the service
sudo systemctl restart openvpn-server@server.service

The client can no longer connect to the OpenVPN server.

Conclusion

This concludes our guide on how to install and configure an OpenVPN server on a Debian 12 server.
 
Top