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:
- Una Certification Authority, identificata da un certificato (pubblico) e da una chiave segreta (eventualmente protetta da password). Questa è l'autorità che genera tutti i certificati che seguono.
- Il server OpenVPN (demone in esecuzione), identificato da un certificato (pubblico) e da una chiave segreta (eventualmente protetta da passowrd). Il certificato è firmato e garantito dalla CA di cui sopra.
- Uno o più client, definiti ciascuno da un certificato (pubblico) e una chiave segreta (in generale non protetta da password). Tutto il necessario per configurare il client viene inserito in un solo file.
- Una chiave segreta supplementare per l'autenticazione TLS. Questa non è strettamente necessaria, ma protegge il server da eventuali attacchi DoS.
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 3653
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
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.
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.
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.
Per ispezionare il certificato della CA (validità, ecc.):
openssl x509 -in pki/ca.crt -text -noout
In Debian 11 Bullseye sembra che ci sia un bug: l'eseguibile /etc/openvpn/easy-rsa/easyrsa è in realtà un link simbolico a /usr/share/easy-rsa/easyrsa. Se eseguito dal link simbolico ignora il contenuto del file /etc/openvpn/easy-rsa/vars. Come workaround si deve fare una copia dell'eseguibile.
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