Install OpenVPN and Easy-RSA

Install and setup Easy-RSA

Install required packages and create a symlink for the easyrsa script

sudo apt update && sudo apt install easy-rsa openvpn -y
mkdir -p ~/easy-rsa
ln -s /usr/share/easy-rsa/easyrsa ~/easy-rsa/easyrsa
cd ~/easy-rsa

Creating a PKI for OpenVPN

Create and edit the vars file using nano or your preferred text editor. The vars file is used when you create the server it will ensure that your private keys and certificate requests are configured to use modern Elliptic Curve Cryptography (ECC) to generate keys and secure signatures for your clients and OpenVPN server.

nano ~/easy-rsa/vars

Once the file is opened, paste in the following lines:

set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"
set_var EASYRSA_CA_EXPIRE 3650  #Set the CA to expire in 10 years
set_var EASYRSA_CERT_EXPIRE 3650 #Set the certificates to expire in 10 years

Initialize the PKI inside the easy-rsa directory:

./easyrsa init-pki

Show the directory structure for Easy-RSA.

./easyrsa |grep -A4 DIRECTORY
DIRECTORY STATUS (commands would take effect on these locations)
     EASYRSA: /home/user/easy-rsa
         PKI: /home/user/easy-rsa/pki
   vars-file: /home/user/easy-rsa/vars
   CA status: CA has not been built

Server Configuration

Build ca.crt and cert/key for server. We are using openvpn-server for the server name.

./easyrsa build-ca nopass
./easyrsa build-server-full openvpn-server nopass

Create the tls-crypt key

The tls-crypt ta.key server directive is being used to encrypt the entire OpenVPN channel (including the handshake control channel) with a pre-shared key, making the traffic harder to identify and providing a defense against port scanning.

To generate the tls-crypt pre-shared key, run the following command in the ~/easy-rsa directory to generate the key. The openvpn command is not in the $PATH for users, so you need to prefix it with the path /usr/sbin.

/usr/sbin/openvpn --genkey secret ta.key

Note

The same ta.key is used by the server and all clients.


Copy the Cert and Keys for the Server

Copy the ca.crt and openvpn-server cert/key to the /etc/openvpn/server/ directory. Set the files to read only and directory user root only for security.

sudo cp ta.key /etc/openvpn/server 
sudo cp ~/easy-rsa/pki/ca.crt /etc/openvpn/server
sudo cp ~/easy-rsa/pki/private/openvpn-server.key /etc/openvpn/server
sudo cp ~/easy-rsa/pki/issued/openvpn-server.crt /etc/openvpn/server
sudo chmod 400 /etc/openvpn/server/.
sudo chmod 700 /etc/openvpn/server

Certificate and key generation is complete.


Configuring the OpenVPN Server

Create the  server.conf  and paste the below server directives into the /etc/openvpn/server.conf.

# Backup any existing /etc/openvpn/server.conf, if one exists. 
sudo mv /etc/openvpn/server.conf /etc/openvpn/server.conf-$(date +%Y%m%d-%H%M%S)
sudo nano /etc/openvpn/server.conf

Insert server directives below into /etc/openvpn/server.conf

port 1194
proto tcp4
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/openvpn-server.crt
key /etc/openvpn/server/openvpn-server.key
tls-crypt /etc/openvpn/server/ta.key
data-ciphers AES-256-GCM
data-ciphers-fallback AES-256-GCM
dh none
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt
# Change this to match your local LAN network subnet.
push "route 10.10.0.0 255.255.255.0"
# If you want all traffic to route through the VPN tunnel, otherwise comment out with ;
# not using means only traffic to your local LAN is routed through the VPN
push "redirect-gateway def1 bypass-dhcp"
# Change this to your DNS IP
push "dhcp-option DNS 10.10.0.1"
push "dhcp-option DOMAIN lan"
topology subnet
keepalive 10 120
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
verb 3
explicit-exit-notify 1
# If web sites are NOT loading once the VPN is up.This is a required directive, if the OpenVPN 
# server or amy of the clients connect via PPPoE, if not you can comment out this directive.
# All DSL and Fiber services for home Internet use PPPoE. Test your max MTU for this value. 
tun-mtu 1432

Explanation of important server directives

Server directive

Value

server

10.8.0.0 255.255.255.0

option server

push route

10.10.0.0 255.255.255.0

option push route

push dhcp-option DNS

10.10.0.1

option dhcp-option DNS

push dhcp-option DOMAIN

lan

dhcp-option DOMAIN

redirect-gateway

redirect-gateway def1 bypass-dhcp

option redirect-gateway

tun-mtu

1432

option tun-mtu

Restart the OpenVPN Server

sudo systemctl restart openvpn.service

Check for any Errors

sudo journalctl -u [email protected] -xe

Setup server to forward IP packets to the Local Network

You need to configure a couple of iptable rules to allow traffic from the VPN to the local network.

IP Forwarding and iptables Configuration

Use as a guide if you are using NAT from the VPN server to the local network. adjust your interface names accordingly.

Enable IP forwarding

sysctl -w net.ipv4.ip_forward=1
# Making the setting permanent by editing /etc/sysctl.conf and adding net.ipv4.ip_forward = 1
sudo nano /etc/sysctl.conf 
sudo sysctl -p

iptables Rules for NAT

These five iptables rules configure the OpenVPN server to function as a router, enabling traffic to pass from the VPN subnet (10.8.0.0/24) to the local network (10.10.0.0/24) and the internet. This allows VPN clients to directly access local resources and to use the local network’s gateway (DSL/Fiber router) for internet access.

To allow Internet routing the OpenVPN server configuration file, located at /etc/openvpn/server.conf, must include the directive:push "redirect-gateway def1 bypass-dhcp"

NAT table: Masquerade VPN client traffic

# replace enp6s18 with your interface name that connects to your lan.
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp6s18 -j MASQUERADE

Mangle table: Clamp MSS for VPN traffic

See this document on how to determine the MTU. Normally only required if the Internet connection is a link with MTU < 1500 bytes, PPPoE for example. Having said that, it is good practice to set when dealing with VPN’s

# replace tun0 with your interface name of your tunnel.
iptables -t mangle -A POSTROUTING -p tcp -o tun0 --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1392

Filter table: Allow VPN clients to access internal network

iptables -A FORWARD -s 10.8.0.0/24 -d 10.10.0.0/24 -j ACCEPT

Analysis of iptables Rules

iptables explained


Client configuration

Create the Client Certificate and Key

cd ~/easy-rsa
./easyrsa build-client-full client-thinkpad nopass

Create .ovpn File for your Client

I have created a BASH script make-client-ovpn.sh to automate this process.

This script generates an all-in-one OpenVPN client configuration file (.ovpn). The script will make an inline file that includes the CA certificate, client certificate, client key, TLS-crypt key, and base config directives.

Download and place in your ~/easy-rsa directory.

cd ~/easy-rsa
wget https://raw.githubusercontent.com/wfahren/OpenVPN/refs/heads/main/make-client-ovpn.sh
chmod +x make-client-ovpn.sh

download script


Create a file with the base client directives

Create client-base.conf file that will have the OpenVPN client directives needed for a client to connect.

cd ~/easy-rsa
nano client-base.conf

Paste the below client directives into the file.

The only directive that you need to change is remote to match your OpenVPN servers address.

# Start client directives
client
dev tun
proto tcp4
data-ciphers AES-256-GCM
data-ciphers-fallback AES-256-GCM
remote yourOpenvpnServer.com 1194 #  can be IP or domainname
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verb 3
# End Client directives

make-client-ovpn usage

The make-client-ovpn.sh script takes only one argument: the client name (e.g., client-thinkpad).

cd ~/easy-rsa
./make-client-config client-thinkpad
Validating required files for client-thinkpad...
Generating OpenVPN configuration for client: client-thinkpad...
SUCCESS: Configuration saved to /home/user/easy-rsa/client-ovpn-files/client-thinkpad.ovpn

The script will create a .ovpn file in the ~/easy-rsa/client-ovpn-files directory that you will use on the client(s).

The script has variables that can be changed if you want to store the .ovpn file somewhere else, or your certificates and key are in a different directory other than /easy-rsa.

EASY_RSA_DIR="$HOME/easy-rsa"                    # Location of easy-rsa directory
CLIENT_CONFIG_DIR="$HOME/easy-rsa"               # Location of client-ovpn-files directory
OUTPUT_DIR="$HOME/easy-rsa/client-ovpn-files"    # Location for client .ovpn files
BASE_CONFIG="$HOME/easy-rsa/client-base.conf"    # Location of client OpenVPN base config