OpenVPN

1. Server

1.1. Installation

sudo apt install openvpn easy-rsa

1.2. Setup

To set up your own CA, and generate certificates and keys for an OpenVPN server with multiple clients, first copy the easy-rsa directory to /etc/openvpn. This will ensure that any changes to the scripts will not be lost when the package is updated.

sudo make-cadir /etc/openvpn/easy-rsa

As root in /etc/openvpn/easy-rsa:

./easyrsa init-pki
./easyrsa build-ca

The PEM passphrase set when creating the CA will be asked for every time you need to encrypt the output of a command (such as a private key).

Generate a key pair for the server:

./easyrsa gen-req <myservername> nopass

Diffie Hellman parameters must be generated for the OpenVPN server. The following command will place them in pki/dh.pem:

./easyrsa gen-dh

And finally, create a certificate for the server:

./easyrsa sign-req server <myservername>

All certificates and keys have been generated in subdirectories. Common practice is to copy them to /etc/openvpn/:

cp pki/dh.pem pki/ca.crt pki/issued/<myservername>.crt pki/private/<myservername>.key /etc/openvpn/

Create the TLS Authentication (TA) key in etc/openvpn:

sudo openvpn --genkey secret ta.key

Edit /etc/sysctl.conf and uncomment the following line to enable IP forwarding:

#net.ipv4.ip_forward=1

Reload sysctl:

sudo sysctl -p /etc/sysctl.conf

[Optional] Copy the example server.conf file to /etc/openvpn/:

sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/myserver.conf.gz
sudo gzip -d /etc/openvpn/myserver.conf.gz
mv myserver.conf server.conf

Edit the /etc/openvpn/server.conf according to your prefences and run OpenVPN client as follows:

sudo systemctl start openvpn@server

1.3. Client key generation

To create the client certificate, enter the following in a terminal as a root user in folder /etc/openvpn/:

./easyrsa gen-req <client_name> nopass
./easyrsa sign-req client <client_name>

client.conf

Copy the following files to the client in the same folder of <client_name>.conf file using a secure method:

  • pki/ca.crt

  • pki/issued/<client_name>.crt

  • pki/private/<client_name>.key

  • ta.key

# Certificate and Key Sections
ca ca.crt
cert <client_name>.crt
key <client_name>.key
tls-crypt ta.key

client.conf

Copy the content of the following files in the <client_name>.ovpn file:

  • pki/ca.crt

  • pki/issued/<client_name>.crt

  • pki/private/<client_name>.key

  • ta.key

# Certificate and Key Sections
<ca>
-----BEGIN CERTIFICATE-----
<content of ca.crt>
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
<content of client_name.crt>
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
<content of client_name.key>
-----END PRIVATE KEY-----
</key>

<tls-crypt>
-----BEGIN OpenVPN Static key V1-----
<content of ta.key>
-----END OpenVPN Static key V1-----
</tls-crypt>

1.4. Client IP assignment

Create the following folder on the server:

sudo mkdir -p /etc/openvpn/ccd

Define the IP address of client with name client_name by creating the file /etc/openvpn/ccd/client_name with this content:

ifconfig-push 10.8.1.2 255.255.255.0

Where 10.8.1.2 is the IP address that will be assigned to the client client_name in the VPN subnet with subnet mask 255.255.255.0.

2. Client

2.1 Installation

sudo apt install openvpn

2.2. Setup

[Optional] Copy the example client.conf file to /etc/openvpn/:

sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/

Then you need to specify ca.crt

Edit /etc/openvpn/client.conf according to your prefences and run OpenVPN client as follows:

$ sudo systemctl start openvpn@client

3. Common setup scenarios

3.1. Split-tunnel

/etc/openvpn/server.conf:

port 1194
proto udp
dev tun

ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-crypt ta.key
cipher AES-256-CBC
auth SHA256
log /var/log/openvpn.log
status /etc/openvpn/status.log

server 10.8.1.0 255.255.255.0  # This creates the VPN subnet (10.8.1.0/24)
ifconfig-pool-persist ipp.txt #every time a user connect to the VPN, its IP address will be the same
ifconfig 10.8.1.1 255.255.255.0 # Set server address to 10.8.1.1
# ifconfig-pool 10.8.1.2 10.8.1.255 #server address (10.8.1.1), pool for clients (10.8.1.2-255)  
client-config-dir /etc/openvpn/ccd # The VPN server assigns the IP address according to the files in this folder (if not specified, IP address of a client can be different every time the client connects to the VPN) 

#push "redirect-gateway def1 bypass-dhcp"  # Route all traffic through the VPN
#push "dhcp-option DNS 8.8.8.8"  # DNS for clients (Google DNS)
push "route 10.8.1.0 255.255.255.0" # Route pushed to the client (IP range accessible for the VPN client)

keepalive 10 120
persist-key
persist-tun

user nobody
group nogroup

verb 4

<client_name>.ovpn:

client
dev tun
proto udp
remote <remote_server_address> 1194  # Server address and port
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA256
cipher AES-256-CBC
verb 3

# Certificate and Key Sections
<ca>
-----BEGIN CERTIFICATE-----
<content of ca.crt>
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
<content of client_name.crt>
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
<content of client_name.key>
-----END PRIVATE KEY-----
</key>

<tls-crypt>
-----BEGIN OpenVPN Static key V1-----
<content of ta.key>
-----END OpenVPN Static key V1-----
</tls-crypt>

# Push DNS or additional routing if needed
push "dhcp-option DNS 8.8.8.8"  # Google DNS or your custom DNS

Full-tunnel

After enabling full tunnel routing, the VPN server needs to be able to masquerade the VPN client's IP addresses when they access the internet. Setup the NAT on the server via iptables:

iptables -t nat -A POSTROUTING -s 10.8.1.0/24 -o eth0 -j MASQUERADE

/etc/openvpn/server.conf:

port 1194
proto udp
dev tun

ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-crypt ta.key
cipher AES-256-CBC
auth SHA256
log /var/log/openvpn.log
status /etc/openvpn/status.log

server 10.8.1.0 255.255.255.0  # This creates the VPN subnet (10.8.1.0/24)
ifconfig-pool-persist ipp.txt # Every time a user connects to the VPN, their IP address will be the same
ifconfig 10.8.1.1 255.255.255.0 # Set server address to 10.8.1.1
client-config-dir /etc/openvpn/ccd # The VPN server assigns the IP address according to the files in this folder

# Enable full tunnel routing (route all traffic through the VPN)
push "redirect-gateway def1 bypass-dhcp"  # Route all traffic through the VPN

# Push DNS settings (Google DNS in this case)
push "dhcp-option DNS 8.8.8.8"  # DNS for clients (Google DNS)

# Push VPN subnet route to clients
push "route 10.8.1.0 255.255.255.0" # Route pushed to the client (IP range accessible for the VPN client)

keepalive 10 120
persist-key
persist-tun

user nobody
group nogroup

verb 4

<client_name>.ovpn:

client
dev tun
proto udp
remote <remote_server_address> 1194  # Server address and port
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA256
cipher AES-256-CBC
verb 3

# Certificate and Key Sections
<ca>
-----BEGIN CERTIFICATE-----
<content of ca.crt>
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
<content of client_name.crt>
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
<content of client_name.key>
-----END PRIVATE KEY-----
</key>

<tls-crypt>
-----BEGIN OpenVPN Static key V1-----
<content of ta.key>
-----END OpenVPN Static key V1-----
</tls-crypt>

# Ensure that all traffic routes through the VPN (Full Tunnel)
redirect-gateway def1 bypass-dhcp

# Optional: Push DNS or additional routing if needed
push "dhcp-option DNS 8.8.8.8"  # Google DNS or your custom DNS

Last updated