OpenVPN “routed” su Debian 9 “Stretch”
Adatto l’articolo OpenVPN “bridged” su Ubuntu 14.04 per Debian 9 “Stretch”.
Una soluzione gratuita e multi-piattaforma è OpenVPN, il sistema è molto potente e versatile e di conseguenza è anche complesso per certi versi.
Nota: Tutte le operazioni vengono fatte dall’utente root.
Installazione server
Innanzitutto installiamo la parte server:
1 |
apt-get install openvpn easy-rsa |
Prepariamo per generare le chiavi:
1 2 3 |
make-cadir /etc/openvpn/certs cd /etc/openvpn/certs ln -s openssl-1.0.0.cnf openssl.cnf |
Modifichiamo i parametri di default che verranno utilizzati nella generazione delle chiavi, quindi apriamo il file vars:
1 |
nano /etc/openvpn/certs/vars |
Impostiamo poi i seguenti valori:
1 2 3 4 5 6 7 8 9 10 |
export KEY_SIZE=4096 ... export KEY_COUNTRY="IT" export KEY_PROVINCE="Roma" export KEY_CITY="Roma" export KEY_ORG="Società di esempio" export KEY_EMAIL="mario@example.com" export KEY_OU="Organizzazione di esempio" ... export KEY_NAME="VPNServer" |
Creazione certificati server
Si procede alla generazione dei certificati del server VPN ( il comando openssl dhparam è facile che impieghi molto tempo a seconda delle prestazioni della macchina ):
1 2 3 4 5 6 |
source vars ./clean-all ./build-ca ./build-key-server server openssl dhparam 4096 > /etc/openvpn/dh4096.pem openvpn --genkey --secret /etc/openvpn/certs/keys/ta.key |
Configurazione server
Procediamo ora alla configurazione del server creando il file server.conf partendo dall’esempio fornito dal pacchetto:
1 |
gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf |
In questo caso procederemo alla configurazione detta routed, la differenza sostanziale tra una bridged e una routed è che la prima funziona come fosse un hub o uno switch virtuale ( quindi mette in connessione due reti che hanno visibilità di classe di IP tra loro ) mentre la seconda si occupa di far dialogare due reti con classi diverse e quindi impossibilitate a vedersi.
Esiste poi anche una versione chiamiamola base che mette in comunicazione solo i client della VPN tra loro oppure solo verso il server, la configurazione è molto più semplice ma per cosa serve a me è troppo limitante quindi la ignoro.
Per le differenze nel dettaglio e i vari pro e contro tra i vari metodi rimando alle documentazioni ufficiali.
Prima di avviare il demone andiamo a modificare il file /etc/openvpn/server.conf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
port 1194 proto udp dev tun ca /etc/openvpn/ca.crt cert /etc/openvpn/server.crt key /etc/openvpn/server.key dh /etc/openvpn/dh4096.pem topology subnet push "topology subnet" server 192.168.8.0 255.255.255.0 ifconfig-pool-persist /etc/openvpn/ipp.txt ;server-bridge 192.168.8.4 255.255.255.0 192.168.8.128 192.168.8.254 push "route 192.168.1.0 255.255.255.0" push "dhcp-option DNS 192.168.1.1" push "dhcp-option WINS 192.168.1.1" push "dhcp-option DOMAIN mydomain.loc" max-clients 10 tls-auth /etc/openvpn/ta.key 0 status openvpn-status.log ;log openvpn.log log-append openvpn.log |
- port: è la porta di ascolto del server VPN, ovviamente questa porta va aperta e reindirizzata dal router;
- proto: il protocollo da utilizzare, tcp o udp, ovviamente questo va a interessare anche la regola di forwarding dal router, in giro consigliano di usare udp in quanto è più veloce la trasmissione e poi tanto il controllo dei dati avviene tramite tun/tap;
- dev: è il metodo di incapsulamento dei dati, tun virtualizza il passaggio di pacchetti IP ( tunnel ) mentre tap virtualizza per intero come un interfaccia ethernet; di solito si mette tun in quanto i dati che transitano sono ridotti, se invece ci sono soluzioni più complesse ad esempio in cui si richiede un bridge di rete ( come nel nostro caso ) occorre usare tap;
- ca, cert, key, dh, tls-auth: questi devono puntare ai certificati del server creati prima;
- topology: di solito si preferisce la tipologia subnet su client recenti, su client windows vecchi occorre commentare l’istruzione per avere tipologia net30 ( vedere la documentazione );
- push “topology …”: nel caso di tipologia subnet questa istruzione serve principalmente se ci sono client Windows o loro prendono comunque la tipologia net30 e non si collegano;
- server: necessaria in caso di VPN routed, se si usa un bridge di rete come nel nostro caso questa voce va commentata;
- server-bridge: qui vanno indicati in ordine l’IP dell’interfaccia di bridge, la maschera di rete del bridge, l’inizio del range di IP da assegnare ai client VPN, la fine del range di IP da assegnare ai client VPN;
- push “route …”: indica ai vari client l’eventuale modifica alla tabella di routing;
- push “dhcp-option …”: indica ai vari client l’eventuale aggiunta di parametri DNS/WINS/DOMAIN;
- max-clients: indica il numero massimo di client VPN che sono accettati, è possibile anche non mettere questo parametri se non si vuole limitare;
- ifconfig-pool-persist: serve a far memorizzare su file le varie assegnazioni degli IP in maniera che ogni client abbia sempre lo stesso indirizzo;
- status: si tratta di un file di log riassuntivo aggiornato ogni minuto dove vengono indicati i client collegati;
- log / log-append: normalmente OpenVPN salva i log nel log di sistema, se vogliamo che per maggiore chiarezza venga salvato a parte basta attivare i parametri log o log-append; la differenza sta che log ad ogni sessione azzera il file e riparte pulito, log-append invece accoda sempre; se indicato solo il nome del file viene salvato nella dir di configurazione ( /etc/openvpn/ );
Ora salviamo e facciamo partire il server:
1 |
service openvpn start |
Se vogliamo vedere i log:
1 |
tail -f /etc/openvpn/openvpn.log |
E’ necessario abilitare il port-forwarding, quindi editiamo i file /etc/sysctl.conf e impostiamo la riga:
1 |
net.ipv4.ip_forward=1 |
Forziamo il caricamento delle regole appena modificate:
1 |
sysctl -p |
Ricordiamo infine di abilitare il traffico attraverso le nostre interfacce con iptables:
1 2 3 4 |
iptables -A INPUT -i tap0 -j ACCEPT iptables -A INPUT -i br0 -j ACCEPT iptables -A FORWARD -i br0 -j ACCEPT iptables -t nat -A POSTROUTING -j MASQUERATING |
Ovviamente queste regole del firewall sono molto generiche e molto insicure, ogni soluzione dovrà poi adottare le proprie restrizioni per garantire una maggiore sicurezza alla rete.
Usare un utente specifico per il servizio
Per migliorare la sicurezza è possibile utilizzare un utente dedicato per far girare openvpn.
Si crea un utente dedicato:
1 |
adduser --system --shell /usr/sbin/nologin --no-create-home openvpn |
Aprire nuovamente /etc/openvpn/server.conf e modificare i valori:
1 2 |
user openvpn group nogroup |
Creazione certificati client
Successivamente occorre creare un certificato per ogni client che necessita il collegamento, al posto di hostname mettiamo il nome identificativo di ogni client in maniera da distinguere poi le chiavi da consegnare ( qui ho preferito usare build-key perchè è in modalità interattiva, quindi per ogni campo della chiave chiede conferma, invece pkitool fa tutto in automatico prendendo in valori dal file vars ):
1 2 3 |
cd /etc/openvpn/certs/ source vars ./build-key name-client-vpn |
Se al certificato per ragioni di sicurezza vogliamo anche associare una password che verrà poi richiesta ad ogni connessione occorre dare invece il comando:
1 |
./build-key-pass nome-client-vpn |
Al client occorre poi fornire i seguenti file e possibilmente è bene non mandarli per email ma usare un metodo di copia cifrata tipo scp o consegnarli a mano su supporto esterno per evitare che vengano intercettati e utilizzati a nostra insaputa:
- /etc/openvpn/certs/keys/ca.crt
- /etc/openvpn/certs/keys/nome-client-vpn.crt
- /etc/openvpn/certs/keys/nome-client-vpn.key
- /etc/openvpn/certs/keys/ta.key
Di questi certificati è consigliabile tenerne sempre una copia anche sul server in quanto se capitasse la necessità di revocarne uno occorre averlo, in fondo aggiungo le operazioni da eseguire per la revoca.
Verificare poi che la cifratura nel client sia la stessa del server, es. AES-256-CBC
Configurazione client Debian
Installiamo ovviamente il pacchetto openvpn:
1 |
apt-get install openvpn |
Copiamo le chiavi del client ( ca.crt, hostname.crt, hostname.key, ta.key ) nella cartella /etc/openvpn.
Copiamo il file di configurazione di esempio per modificarlo:
1 |
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn |
Editiamolo e impostiamo con i parametri del server:
1 2 3 4 5 6 7 |
dev tun proto udp remote [ip o host del server] 1194 ca ca.crt cert hostname.crt key hostname.key tls-auth ta.key 1 |
In questo caso a differenza della configurazione del client per Windows che vedremo dopo è che le direttive push del server ( esempio per avere la risoluzione DNS ) potrebbero non avvenire in automatico, nel caso serve impostarle a mano magari tramite uno script che come recita la pagina ufficiale analizzi la variabile d’ambiente foreign_option_*:
Windows clients can accept pushed DHCP options natively, while non-Windows clients can accept them by using a client-side up script which parses the foreign_option_n environmental variable list.
Attualmente nessuna delle soluzioni che ho trovato in giro hanno funzionato, l’unica per avere anche la risoluzione dei DNS è quella di editare a mano il file /etc/resolv.conf e aggiungere come prima riga la voce nameserver x.x.x.x ( dove per x.x.x.x si intende l’ip del server DNS dietro VPN ).
Facciamo partire il servizio:
1 |
service openvpn restart |
Se vogliamo vedere i log:
1 |
tail -f /etc/openvpn/openvpn.log |
Configurazione client Windows
Il pacchetto che andremo a usare sarà quello ufficiale di OpenVPN scaricabile dal sito a questo indirizzo:
http://openvpn.net/index.php/open-source/downloads.html
Installiamo il pacchetto che di default si installa in C:\Programmi\OpenVPN
Andiamo in quel percorso e spostiamo nella cartella sample-config al cui inteno ci sono i file di configurazione standard, a noi interessa il file client.ovpn
Copiamo il file nella cartella C:\Programmi\OpenVPN\config, volendo se abbiamo una sola configurazione possiamo usare direttamente questa, ma per pulizia io preferisco creare un ulteriore sotto cartella per ogni configurazione che abbiamo, quindi ad esempio creiamo la cartella vpn-prova e spostiamoci dentro il file client.ovpn ( magari rinominiamolo come la cartella sempre per pulizia, quindi vpn-prova.ovpn ) e anche i quattro file dei certificati client che abbiamo creato prima ( ca.crt, hostname.crt, hostname.key, ta.key ).
Ora apriamo con il notepad o qualsiasi editor di testo il file vpn-prova.ovpn e andiamo a modificare le seguenti righe con i dati del server come nell’esempio
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
client dev tun proto udp remote [ip o host del server] 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt cert hostname.crt key hostname.key remote-cert-tls server tls-auth ta.key 1 cipher AES-256-CBC #comp-lzo verb 3 |
A questo punto possiamo salvare e chiudere.
Utilizzare un IP statico per i vari client
Creare se manca la cartella ccd:
1 |
mkdir /etc/openvpn/ccd |
Nel file di configurazione del server decommentare o aggiungere l’istruzione:
1 |
client-config-dir ccd |
Creare un file di configurazione con lo stesso nome del client di cui si vuole l’ip statico:
1 2 |
cd /etc/openvpn/ccd nano client1 |
Inserire l’indirizzo richiesto nel formato:
1 |
ifconfig-push <IP> <MASK> |
Riavviare il server:
1 |
service openvpn restart |
Indicare un range di indirizzi disponibili
La modalità routed con il parametro server utilizza il .1 come IP del server mentre dedica tutti gli altri ai client VPN,nel caso volessimo ridurre questo range per poter utilizzare anche IP statici occorre commentare il parametri server e aggiungere gli altri valori:
1 2 3 4 5 6 7 8 9 |
;server 10.8.0.0 255.255.255.0 mode server tls-server ifconfig 10.8.0.1 255.255.255.0 push "route-gateway 10.8.0.1" ifconfig-pool 10.8.0.2 10.8.0.199 topology subnet push "topology subnet" client-config-dir ccd |
Nel caso di interfaccia tun non si mette la netmask a ifconfig-pool.
Riavviare il server:
1 |
service openvpn restart |
Revoca di un certificato
In caso si volesse revocare un certificato ( magari perchè è stato rubato o perso ) occorre seguire alcuni semplici punti, occorre però avere copia del certificato da revocare, per quello prima si consigliava di non cancellarli mai dal server:
1 2 3 |
cd /etc/openvpn/certs/keys/ source vars ./revoke-full client1 |
Dopo un po’ di messaggi uscirà un error 23 at 0 depth lookup:certificate revoked che sta a indicare che il certificato è stato revocato e sarà creato un file crl.pem con l’elenco dei certificati revocati.
Questo file va copiato nella cartella con le altre chiavi del server:
1 |
cp crl.pem /etc/openvpn/ |
Controllate nella configurazione del server che esista la riga ( altrimenti aggiungetela ):
1 |
crl-verify /etc/openvpn/crl.pem |
Riavviare il server:
1 |
service openvpn restart |
Attivare il logrotate sui log custom
Se abbiamo attivato i log nel percorso custom /etc/openvpn/openvpn.log e se abbiamo utilizzato il metodo append conviene attivare anche il logrotate per non saturare in breve tempo lo spazio specialmente su minidispositivi o serverini virtuali.
Creare il file di configurazione /etc/logrotate.d/openvpn :
1 2 3 4 5 6 7 |
/etc/openvpn/openvpn.log { rotate 7 weekly compress missingok notifempty } |
Per provarlo, forzarne l’avvio a mano:
1 |
logrotate -f -v /etc/logrotate.d/openvpn |
Visualizzare i client collegati
Per vedere quali utenti sono collegati alla VPN si può guardare nel file openvpn-status.log oppure se si vuole un monitoraggio costante senza aprire e chiudere il file di status si aggiunge l’istruzione:
1 |
management localhost 6666 |
al file server.conf ( o al posto di 6666 una porta qualsiasi ).
Per collegarsi alla console:
1 |
telnet localhost 6666 |
e poi dare il comando:
1 |
status |
Eseguire operazioni alla connessione dei client
Al file server.conf aggiungere:
1 2 3 |
script-security 2 client-connect ./client-connect.sh client-disconnect ./client-disconnect.sh |
Il parametro script-security 2 permette a openvpn di eseguire anche gli script, senza quello con il valore di default 1 può eseguire solo i binari installati ( tipo ifconfig, ip, route o netsh ).
Questo se vogliamo eseguire determinati script alla connessione/disconnessione dei client, la disconnessione comunque potrebbe avvenire per timeout non effettivamente quando un client si disconnette.
Esempio client-connect.sh:
1 2 3 4 5 6 7 |
#!/bin/bash # This is an openvpn connect script that log users connection # ${ifconfig_pool_remote_ip} is IP/Subnet/MAC # ${common_name} is certificate's common name # test -f /var/log/openvpn/conn.log || touch /var/log/openvpn/conn.log echo "`date` - connect - CN: ${common_name} has IP: ${ifconfig_pool_remote_ip}" >> /var/log/openvpn/conn.log |
Esempio client-disconnect.sh:
1 2 3 4 5 6 7 |
#!/bin/bash # This is an openvpn disconnect script that log user # ${ifconfig_pool_remote_ip} is IP/Subnet/MAC # ${common_name} is certificate's common name # test -f /var/log/openvpn/conn.log || touch /var/log/openvpn/conn.log echo "`date` - disconnect - CN: ${common_name} from IP ${ifconfig_pool_remote_ip}" >> /var/log/openvpn/conn.log |