Configure EgdeRouter OpenVPN

Lars Jönsson 2024-02-17

How to setup an OpenVPN server on EdgeRouter with password protected client keys using a separate CA. The CA uses the easy-rsa 3 script to ensure that the certificates suits hardened OpenVPN security.

This guide consists of three parts:

Overview

The OpenVPN server is setup according to the official guide EdgeRouter - OpenVPN Server, with the main difference that the Certificate Authority (CA) is outside the EdgeRouter. This makes it easier to improve the security.

The different key and certificate files, used by OpenVPN server and clients, are used as follows:

Filename Needed By Purpose Secret
ca.crt server + all clients Root CA certificate NO
ca.key key signing machine only Root CA key YES
dh{n}.pem server only Diffie Hellman parameters NO
server.crt server only Server Certificate NO
server.key server only Server Key YES
client1.crt client1 only Client1 Certificate NO
client1.key client1 only Client1 Key YES
client2.crt client2 only Client2 Certificate NO
client2.key client2 only Client2 Key YES
client3.crt client3 only Client3 Certificate NO
client3.key client3 only Client3 Key YES

All non-secret parts, as certificates, Diffie-Hellman key and Certification Revocation List, are generated on the CA. The secret parts are as follows:

  • The server key is generated on the server and never leaves the server
  • The CA key is generated on the CA and never leaves the CA
  • The client keys are also generated on the CA, but they are always password protected and it shall not be a problem to move it to the clients as a part of a configuration file

Preparations

The CA is created on a Linux computer that runs Fedora 32. The easy-rsa 3 package (see OpenVPN/easy-rsa) will be used for managing the certificates. The entire CA will be stored on a safe storage (see Safe storage) that can be stored on a USB stick, but these instructions assumes that the safe storage is stored locally on the Linux computer.

Install the easy-rsa package.

sudo dnf install easy-rsa

Create the base of the OpenVPN CA at ~/OpenVPN-CA.

cd
mkdir OpenVPN-CA
cd ~/OpenVPN-CA

Create a safe storage for the pki.

dd if=/dev/zero bs=1M count=100 of=secret-device.img
sudo cryptsetup luksFormat secret-device.img
sudo cryptsetup open --type luks secret-device.img secret-device
sudo mkfs.ext4 /dev/mapper/secret-device
mkdir safe-storage
sudo mount /dev/mapper/secret-device safe-storage
sudo chown $USER:`id -gn` safe-storage

Create a link to the easyrsa script and copy the example configuration file.

cd safe-storage
ln -s /usr/share/easy-rsa/3/easyrsa
cp /usr/share/doc/easy-rsa/vars.example vars

Create CA

By default, the CA root certificate expires after 10 years, signed certificates expires after 2 years and the revocation list (CRL) expires are 180 days.

Set the expire date to 10 years for all by setting these varibles in the vars file.

set_var EASYRSA_CERT_EXPIRE 3650
set_var EASYRSA_CRL_DAYS    3650

Initialize the pki.

cd ~/OpenVPN-CA/safe-storage
./easyrsa init-pki

Build the CA.

./easyrsa build-ca

Create OpenVPN server

Configuring the OpenVPN server follows the official guide EdgeRouter - OpenVPN Server with some modifications.

Create key and CSR on the EdgeRouter

Login to the EgdeRouter and create the key/CSR (Certificate Signing Request). Select a temporary password and enter '.' in the other fields, except the Common Name, to make them empty.

sudo su
cd /usr/lib/ssl/misc
./CA.pl -newreq
Enter PEM pass phrase: <TEMPORARY_PASS>
Verifying - Enter PEM pass phrase: <TEMPORARY_PASS>
Common Name: server

Sign the CSR on the CA

Move and rename the server key file to the /config/auth directory and remove the password.

mv newkey.pem /config/auth/server.key
openssl rsa -in /config/auth/server.key -out /config/auth/server-no-pass.key
mv /config/auth/server-no-pass.key /config/auth/server.key 

Return to operational mode. There is no need to logout from the EdgeRouter at this point, as we will soon come back and configure the OpenVPN server.

exit

Return to the Linux computer to copy the CSR from the EdgeRouter and import it into the CA.

scp admin@192.168.0.1:/usr/lib/ssl/misc/newreq.pem .
./easyrsa import-req newreq.pem server
rm newreq.pem

Sign the CSR and copy the certificate to the EdgeRouter.

./easyrsa sign-req server server
scp pki/issued/server.crt admin@192.168.0.1:/config/auth/server.pem

Create the Certificate Revocation List (CRL) and copy it to the EdgeRouter.

./easyrsa gen-crl
scp pki/crl.pem admin@192.168.0.1:/config/auth/

Copy the CA certificate to the EdgeRouter.

scp pki/ca.crt admin@192.168.0.1:/config/auth/cacert.pem

The OpenVPN server uses a Diffie-Hellman key. I can be generated on the EdgeRouter, but it takes a very long time (more than 30 minutes). It is much faster (less than one minute) to generate it on the Linux computer and copy it to the EdgeRouter.

Generate the key and copy it to the EdgeRouter.

./easyrsa gen-dh
scp pki/dh.pem admin@192.168.0.1:/config/auth/

Lock up the safe storage if all CA work is done.

Configure the OpenVPN server

NOTE When changing any of the TLS files like certificates and CRL, the openvpn configuration needs to be removed and recreated. Maybe it is enough to just remove and recreate the interfaces openvpn vtun0 tls part, but that has not been tested. According to the community, interfaces openvpn vtun0 needs to be removed and recreated.

The OpenVPN server is now ready to be configured. Go back to the EgdeRouter and login, if needed.

Enter configuration mode.

configure

Add a firewall rule for the OpenVPN traffic to the WAN_LOCAL firewall policy.

set firewall name WAN_LOCAL rule 30 action accept
set firewall name WAN_LOCAL rule 30 description openvpn
set firewall name WAN_LOCAL rule 30 destination port 1194
set firewall name WAN_LOCAL rule 30 protocol udp

Configure the OpenVPN virtual tunnel interface. Ensure that name-server and push-route corresponds to the used addresses.

set interfaces openvpn vtun0 mode server
set interfaces openvpn vtun0 server subnet 172.16.1.0/24
set interfaces openvpn vtun0 server push-route 192.168.0.0/24
set interfaces openvpn vtun0 server name-server 192.168.0.1

Setup aes256 encryption to improve security.

set interfaces openvpn vtun0 encryption aes256

Link the server certificate/keys and DH key to the virtual tunnel interface.

set interfaces openvpn vtun0 tls ca-cert-file /config/auth/cacert.pem
set interfaces openvpn vtun0 tls cert-file /config/auth/server.pem
set interfaces openvpn vtun0 tls key-file /config/auth/server.key
set interfaces openvpn vtun0 tls crl-file /config/auth/crl.pem
set interfaces openvpn vtun0 tls dh-file /config/auth/dh.pem

Add the virtual tunnel interface to the DNS forwarding interface list.

set service dns forwarding listen-on vtun0

Commit the changes and save the configuration.

commit ; save

Return to operational mode.

exit

The OpenVPN server is now up and running. Logout from the EdgeRouter and go ahead to create client configuration(s).

Create OpenVPN Client configuration

First Open the safe storage, if needed.

For convenience, the OpenVPN server name and client name, are set in environment variables.

NOTE Replace example.com with the name of the name of the OpenVPN server and client1 with an appropriate client name.

ovpn_server=example.com
ovpn_client=client1

Change to the OpenVPN CA directory.

cd ~/OpenVPN-CA/safe-storage

Generate the certificate and key files for the client. Remember the password of the private key as it needs to entered when the client connects to the server.

./easyrsa gen-req $ovpn_client

Sign the certificate.

./easyrsa sign-req client $ovpn_client

Create the OpenVPN client file.

{
echo "client"
echo "dev tun"
echo "proto udp"
echo "remote $ovpn_server 1194"
echo "float"
echo "resolv-retry infinite"
echo "nobind"
echo "persist-key"
echo "persist-tun"
echo "verb 3"
echo "cipher AES-256-CBC"
echo "auth-nocache"
echo "remote-cert-tls server"
echo "<ca>"
openssl x509 -in pki/ca.crt
echo "</ca>"
echo "<cert>"
openssl x509 -in pki/issued/$ovpn_client.crt
echo "</cert>"
echo "<key>"
cat pki/private/$ovpn_client.key
echo "</key>"
} > $ovpn_client.ovpn

An .ovpn file similar to this should be created:

client
dev tun
proto udp
remote example.com 1194
float
resolv-retry infinite
nobind
persist-key
persist-tun
verb 3
cipher AES-256-CBC
auth-nocache
remote-cert-tls server
<ca>
-----BEGIN CERTIFICATE-----
MIIDvTCCAqWgAwIBAgIJANvkOPYA/0TTMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
  ...
pg==
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIID4jCCAsqgAwIBAgIJANvkOPYA/0TVMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
  ...
ULQvAqMyg3hvUoMU2PUwvh0wCUoKjZ7ewv3kXYZZ6KJcGJ+B610=
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIcjdGY+dkxccCAggA
  ...
xIk=
-----END ENCRYPTED PRIVATE KEY-----
</key>

Import the .ovpn file to the OpenVPN client software. Use the clients private key password when connecting to the server.

Lock up the safe storage if all CA work is done.

Renew certificate for OpenVPN Client

NOTE The steps in this section is not verified, because the expiration date of the client certificates and is set to 10 years now.

First Open the safe storage, if needed.

For convenience, the OpenVPN server name and client name, are set in environment variables.

NOTE Replace example.com with the name of the name of the OpenVPN server and client1 with an appropriate client name.

ovpn_server=example.com
ovpn_client=client1

Change to the OpenVPN CA directory.

cd ~/OpenVPN-CA/safe-storage

Renew the certificate and using the existing key file for the client. Use the current password of the private key, which is also entered when the client connects to the server.

./easyrsa renew $ovpn_client

Create the OpenVPN client file.

{
echo "client"
echo "dev tun"
echo "proto udp"
echo "remote $ovpn_server 1194"
echo "float"
echo "resolv-retry infinite"
echo "nobind"
echo "persist-key"
echo "persist-tun"
echo "verb 3"
echo "cipher AES-256-CBC"
echo "auth-nocache"
echo "remote-cert-tls server"
echo "<ca>"
openssl x509 -in pki/ca.crt
echo "</ca>"
echo "<cert>"
openssl x509 -in pki/issued/$ovpn_client.crt
echo "</cert>"
echo "<key>"
cat pki/private/$ovpn_client.key
echo "</key>"
} > $ovpn_client.ovpn

An .ovpn file similar to this should be created:

client
dev tun
proto udp
remote example.com 1194
float
resolv-retry infinite
nobind
persist-key
persist-tun
verb 3
cipher AES-256-CBC
auth-nocache
remote-cert-tls server
<ca>
-----BEGIN CERTIFICATE-----
MIIDvTCCAqWgAwIBAgIJANvkOPYA/0TTMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
  ...
pg==
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIID4jCCAsqgAwIBAgIJANvkOPYA/0TVMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV
  ...
ULQvAqMyg3hvUoMU2PUwvh0wCUoKjZ7ewv3kXYZZ6KJcGJ+B610=
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIcjdGY+dkxccCAggA
  ...
xIk=
-----END ENCRYPTED PRIVATE KEY-----
</key>

Import the .ovpn file to the OpenVPN client software. Use the clients private key password when connecting to the server.

Lock up the safe storage if all CA work is done.

Revoke certificates

Sometimes certificates needs to be revoked. Typical reasons for wanting to revoke a certificate include:

  • The private key associated with the certificate is compromised or stolen.
  • The user of an encrypted private key forgets the password on the key.
  • You want to terminate a VPN user’s access.

First Open the safe storage, if needed.

NOTE Replace client1 with the name of your certificate

cd ~/OpenVPN-CA/safe-storage
./easyrsa revoke client1

Rebuild the crl file and copy it to the OpenVPN server.

./easyrsa gen-crl
scp pki/crl.pem admin@192.168.0.1:/config/auth/

There is no need to restart the OpenVPN server, because the uploaded crl file will be used at the next connection attempt.

Lock up the safe storage if all CA work is done.

Safe storage usage

Open safe storage

Before the CA can be used, the safe storage needs to opened.

cd ~/OpenVPN-CA
sudo cryptsetup open --type luks secret-device.img secret-device
sudo mount /dev/mapper/secret-device safe-storage

Lock up safe storage

When all certificates are created, the safe storage can be locked up (and optionally stored in a safe place).

cd ~/OpenVPN-CA
sudo umount safe-storage
sudo cryptsetup close secret-device