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
We are using the tls-crypt ta.key server option, to not only authenticate, but also encrypt the TLS control channel.
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 accessible for non-root users; sudo is required to create the key.
sudo openvpn --genkey secret ta.key
note: You will only do this once. The same ta.key is used by the server and all clients.
Since we created the ta.key using sudo, we need to change the ownership from root to your current user. We will later use this file when we create the client .ovpn file as non-root.
sudo chown $USER: ta.key
Copy the Cert and Keys for the Server
Copy the ca.crt and openvpn-server cert/key to the /etc/openvpn/server/ directory.
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
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 (options) below into /etc/openvpn/server.conf
port 1194
proto udp4
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 option, if the OpenVPN
# server or amy of the clients connect via PPPoE, if not you can comment out this option.
# All DSL and Fiber services for home Internet use PPPoE. Test your max MTU for this value.
tun-mtu 1432
Explanation of important server options
Server Option |
Value |
|
|---|---|---|
server |
10.8.0.0 255.255.255.0 |
|
push route |
10.10.0.0 255.255.255.0 |
|
push dhcp-option DNS |
10.10.0.1 |
|
push dhcp-option DOMAIN |
lan |
|
redirect-gateway |
redirect-gateway def1 bypass-dhcp |
|
tun-mtu |
1432 |
Restart the OpenVPN Server
sudo systemctl restart openvpn.service
Check for any Errors
sudo journalctl -u openvpn@server.service -xe
Sutup 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 connection is a link with MTU >1500 bytes, DSL 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
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 options.
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
Create a file with the base client options
Create client-base.conf file that will have the OpenVPN client options needed for a client to connect.
cd ~/easy-rsa
nano client-base.conf
Paste the below client options into the file.
The only option that you need to change is remote to match your OpenVPN servers address.
# Start client options
client
dev tun
proto udp4
data-ciphers AES-256-GCM
data-ciphers-fallback AES-256-GCM
remote yourOpenvpnServer.com 1194 # can be IP or domainname
resolv-retry infinite
nobind
key-direction 1
persist-key
persist-tun
remote-cert-tls server
verb 3
# End Client option
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