Table of Contents

OpenVPN con Easy-RSA

In generale la creazione di certificati e chiavi RSA avviene con l'utilizzo del comando openssl. Tuttavia una configurazione completa di OpenVPN con tale strumento è abbastanza complessa (vedere in proposito la pagina OpenVPN con chiave RSA), utilizzare il tool Easy RSA semplifica notevolmente il lavoro.

In Debian, a partire dalla versione 8 Jessie, esiste il pacchetto easy-rsa che facilita la configurazione di OpenVPN con chiavi RSA. Tale sistema si contrappone al metodo PSK, cioè a chiave segreta condivisa. Alcuni client più recenti non accettano di essere configurati con PSK, ad esempio il client Android di OpenVPN 3.2.5

Sul server OpenVPN si devono gestire tre componenti:

Preparazione della directory

Anzitutto si prepara la directory che conterrà i certificati, ecc:

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

La directory easy-rsa non deve esistere, viene creata e inizializzata con contenuti predefiniti.

cd easy-rsa/
./easyrsa init-pki

Con questo comando viene creato il file ./pki/openssl-easyrsa.cnf e le cartelle ./pki/private/ e ./pki/reqs/ destinate a contenere certificati e chiavi.

Creazione della CA

Prima di creare il certificato della Certification Authority e la relativa chiave privata, si deve editare il file vars per impostare almeno le seguenti variabili:

set_var EASYRSA_REQ_COUNTRY    "US"
set_var EASYRSA_REQ_PROVINCE   "California"
set_var EASYRSA_REQ_CITY       "San Francisco"
set_var EASYRSA_REQ_ORG        "Copyleft Certificate Co"
set_var EASYRSA_REQ_EMAIL      "me@example.net"
set_var EASYRSA_REQ_OU         "My Organizational Unit"

set_var EASYRSA_CA_EXPIRE      3653
set_var EASYRSA_CERT_EXPIRE    1826

La durata in giorni della CA e dei singoli certificati per i client è ovviamente fondamentale e si dovrà gestire accortamente le scadenze, che sono difficilmente aggirabili.

La creazione della Certification Authority va effettuata una sola volta e dura per tutto il tempo specificato da EASYRSA_CA_EXPIRE.

./easyrsa build-ca nopass

Omettendo il parametro nopass viene chiesta una passphrase, che servirà in futuro a firmare i certificati rilasciati da questa CA (è in effetti la password necessaria a sbloccare la chiave privata della CA). Con il parametro nopass si evita di dover digitare una password in tutte le operazioni seguenti; la sicurezza è garantita dal fatto che solo root può accedere alla cartella easy-rsa.

Durante questo passaggio viene chiesto il Common Name della certification authority, in generale si può identificare il CN con il nome host della macchina che gestisce l'infrastruttura PKI.

Di tutti i file creati, i più importanti sono ./pki/ca.crt e ./pki/private/ca.key che sono rispettivamente il certificato della CA (pubblico) e la relativa chiave privata. Oltre a quelli, sempre nella directory ./pki/, ci sono le direcotry per contentere le revocation lists, ecc.

Generazione di certificato e chiave per il server

./easyrsa build-server-full server_name nopass

In mancanza dell'opzione nopass viene chiesta una PEM pass phrase per proteggere la chiave del server, tale password andrà digitata tutte le volte che si avvia il server OpenVPN. La chiave privata verrà salvata in un file ./pki/private/server_name.key, il certificato pubblico invece in ./pki/issued/server_name.crt. Il file con la request intermedia viene creato in ./pki/reqs/server_name.req.

Viene anche chiesta la password per sbloccare la chiave della CA, che deve essere usata per firmare il certificato del server.

Generazione della chiave Diffie-Hellman

Si esegue il comando:

./easyrsa gen-dh

Viene creato il file /etc/openvpn/easy-rsa/pki/dh.pem. Questo file verrà usato direttamente dal file di configurazione di OpenVPN.

Generazione di una chiave statica per autenticazione TLS

È opportuno creare una chiave precondivisa per la TLS Authentication:

# Deprecated: openvpn --genkey --secret /etc/openvpn/server/ta.key
openvpn --genkey tls-auth /etc/openvpn/server/ta.key

Questa viene utilizzata nella fase iniziale del TLS, per evitare attacchi di tipo DoS, in pratica un client privo di questa chiave viene bloccato prima di tentare una connessione.

Configurazione del server

Dopo aver creato tutti i file visti in precedenza, si può creare il file di configurazione OpenVPN, /etc/openvpn/server_name.conf:

#---------------------------------------------------------------
# OpenVPN configuration for Easy-RSA server.
#---------------------------------------------------------------
verb 3
status /var/log/openvpn/openvpn-status.log
lport 1194
proto udp
dev tun
ca   /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server_name.crt
key  /etc/openvpn/easy-rsa/pki/private/server_name.key
dh   /etc/openvpn/easy-rsa/pki/dh.pem
# If you revoke some certificate, you need the Certificate Revocation List:
crl-verify /etc/openvpn/easy-rsa/pki/crl.pem

mode server
tls-server
topology subnet
push "topology subnet"
ifconfig 10.9.8.1 255.255.255.0
# Allocate some IP address for dynamic client configuration.
# Dynamic pool must not overlap static ifconfig-push options.
ifconfig-pool 10.9.8.2 10.9.8.127 255.255.255.0
# Allow per-client static configuration (one file per client).
client-config-dir /etc/openvpn/client
ifconfig-pool-persist ipp.txt
push "route-gateway 10.9.8.1"
# Route only the the local LAN.
push "route 192.168.0.0 255.255.255.0"
# Route all the traffic through the VPN.
#push "redirect-gateway autolocal"

keepalive 10 120
tls-auth /etc/openvpn/server/ta.key 0
auth-nocache
auth SHA256
# Avoid default BF-CBC cipher, because of its 64-bit block size.
cipher AES-256-CBC
persist-key
persist-tun
client-to-client
explicit-exit-notify 1

Finché non si è revocato alcun certificato, il file easy-rsa/pki/crl.pem non esiste (vedi più avanti), in tal caso è necessario commentare l'opzione crl-verify.

Nella configurazione sopra viene allocato un pool di indirizzi IP per la configurazione dinamica dei client (opzione ifconfig-pool), inoltre si dispone una directory dove creare dei file personalizzati per ciascun client (opzione client-config-dir). Nei file personalizzati si potrà ad esempio inserire l'opzione ifconfig-push per forzare un IP statico ad un determinato client (nota bene, l'IP statico deve essere fuori dal pool dinamico).

Nella configurazione sopra, il client utilizza la VPN solo per raggiungere la rete privata indicata da push route, mantenendo il proprio default gateway.

Per avviare il servizio:

systemctl enable openvpn@server_name
systemctl start openvpn@server_name

Se la chiave del server è protetta da password viene mostrato un messaggio broadcast su tutti terminali:

Password entry required for 'Enter Private Key Password:' (PID 18485).
Please enter password with the systemd-tty-ask-password-agent tool:

Come suggerito dal comando, si esegue:

systemd-tty-ask-password-agent
Enter Private Key Password: *************

Ovviamente non sarà possibile avviare OpenVPN automaticamente al boot in questo caso.

Generazione del certificato e chiave per un client

Questo passaggio va ripetuto per ogni client che si deve connettere, si deve ovviamente specificare un clientname diverso ogni volta:

./easyrsa build-client-full [clientname] nopass

Il parametro nopass è necessario per consentire l'avvio della VPN sul client senza digitare una password.

Per la creazione del certificato viene chiesta la password per sbloccare la chiave della CA.

Il certificato viene creato in ./pki/issued/clientname.crt, viene anche creata una copia esatta in ./pki/certs_by_serial/[hash].pem.

File di configurazione per il client

Questo è un esempio di file di configurazione per un client, con certificati e chiavi inline, cioè contenuti nel file stesso. È necessario personalizzare l'indirizzo IP del server nell'opzione remote:

#====================================================
# OpenVPN configuration file
#====================================================
verb 3
client
pull
remote 10.0.1.189 1194
# Routing is pushed by the server.
#route-gateway dhcp
# Route only the remote LAN.
#route 192.168.1.0 255.255.255.0 vpn_gateway
# Route all the internet traffic through the VPN.
#redirect-gateway autolocal
remote-cert-tls server
resolv-retry infinite
proto udp
dev tun1
tls-client
reneg-sec 60
key-direction 1
# The --cipher option is used to connect OpenVPN older than 2.6.0.
#cipher AES-256-CBC
# Newer connections using TLS uses the --data-ciphers option.
data-ciphers AES-256-GCM:AES-128-GCM
auth SHA256
auth-nocache

<ca>
-----BEGIN CERTIFICATE-----
... content of /etc/openvpn/easy-rsa/pki/ca.crt
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
... content of /etc/openvpn/easy-rsa/pki/issued/clientname.crt
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
... content of /etc/openvpn/easy-rsa/pki/private/clientname.key
-----END PRIVATE KEY-----
</key>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
... content of /etc/openvpn/server/ta.key
-----END OpenVPN Static key V1-----
</tls-auth>

Configurazione push

Quando un client si connette alla VPN viene aggiunta una riga al file /etc/openvpn/ipp.txt, con il formato:

clientname,10.9.8.2,

Questo serve ad assegnare possibilimente sempre lo stesso IP al client. Se si vuole avere maggiore certezza dell'indirizzo IP assegnato al client, è necessario creare un file con le impostazioni push, ad esempio il file /etc/openvpn/client/clientname con:

ifconfig-push 10.9.8.128 255.255.255.0

È necessario riavviare il servizio per rendere effettive le modifiche.

Elenco dei certificati creati e revoca

cd /etc/openvpn/easy-rsa
cat pki/index.txt

Il flag V indica i certificati validi:

V  261011105054Z                 317F73DAF2BF2A44C21BC804024E0C5B  unknown /CN=client-name1
V  261012161858Z                 31185709CFD614AD3F87526A386B06CF  unknown /CN=client-name2

Per revocare un certificato (ad esempio quello con nome client-name2) si usa il comando:

./easyrsa revoke client-name2

Il file pki/issued/<client-name2>.crt viene rimosso e il file pki/index.txt viene aggiornato con la data di scadenza:

V  261011105054Z                 317F73DAF2BF2A44C21BC804024E0C5B  unknown /CN=client-name1
R  261012161858Z  230919101036Z  31185709CFD614AD3F87526A386B06CF  unknown /CN=client-name2

Quindi è necessario creare la nuova Certificate Revocation List, altrimenti il client potrà sempre utilizzare il certificato:

./easyrsa gen-crl

Viene aggiornato il file pki/crl.pem con la nuova Certificate Revocation List, assicurarsi quindi che il file di configurazione del server abbia l'opzione crl-verify che punta a questo file.

Per vedere il contenuto della CRL e la sua scadenza si usa il comando:

openssl crl -in pki/crl.pem -noout -text

Nel'opportuna sezione si potranno leggere delle righe del tipo:

Revoked Certificates:
    Serial Number: 31185709CFD614AD3F87526A386B06CF
        Revocation Date: Sep 19 10:45:13 2023 GMT

Poichè la CRL ha una scadenza è necessario un cronjob che periodicamente la rinnovi (il tempo di vita predefinito è di 180 giorni). Ecco ad esempio uno script adeguato:

#!/bin/sh
# Generate a new Certificate Revocation List into the EasyRSA directory.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
cd /etc/openvpn/easy-rsa
./easyrsa gen-crl

Web References