Guida a OpenVPN per GNU/Linux

08Gen11

Come forse saperete avevo già fatto tempo fa una guida per creare la propria VPN su GNU/Linux.
Recentemente ho scritto un articolo per un giornalino redatto dal POuL (Politecnico Open unix Labs) in proposito. Dato che è passato parecchio tempo da quando ho iniziato a sperimentare le VPN e ora so molto di più, ho voluto riassumere il tutto in una breve guida, che introduce anche al concetto di cosa sia una VPN.

Introduzione

Un po’ per necessità, un po’ per interesse, ho scoperto e iniziato ad utilizzare OpenVPN. Inizialmente non avevo ben capito come funzionasse tutto e non riuscivo a trovare una guida semplice in italiano in rete per fare quello che avevo bisogno, quindi eccola qua! Nella scrittura della guida ho supposto che il lettore abbia un minimo di conoscenza della bash e dei comandi fondamentali per l’amministrazione di sistema GNU/Linux. Le righe precedute da “#” indicano dei comandi dati da terminale. Vi prego di notificarmi la presenza di eventuali errori presenti. Non mi assumo nessuna responsabilità sull’utilizzo proprio o improprio delle informazioni qui presentate.

VPN, Virtual Private Network, questa sconosciuta

Che cos’è una VPN? Iniziamo introducendo tramite un esempio il concetto di VPN (Virtual Private Network).
Supponiamo di avere un ufficio con dieci computer a Milano, un server a Roma e un portatile a Tokyo, tutti collegati ad Internet. I dieci computer di Milano sono dietro ad un router che ne isola l’accesso da parte dell’esterno, tramite un firewall e una NAT; mentre il server di Roma è direttamente accessibile da Internet (ha cioè quello che si definisce spesso un “IP pubblico”).
A questo punto noi siamo sul portatile a Tokyo e vogliamo accedere tramite SSH, FTP, SFTP o qualunque altro servizio a certi dati sui computer dell’ufficio di Milano che sono “dietro” al firewall+NAT. Per fare ciò (escludendo operazioni sul router dell’ufficio), la soluzione più comoda per vari motivi potrebbe essere una VPN. Tramite una VPN, infatti, possiamo fare in modo che, ovunque siamo, è come se fossimo collegati con un cavo al server di Roma. Per realizzare una VPN ci sono tanti programmi ed il più usato e probabilmente anche migliore tra tutti è OpenVPN.
In una struttura come quella descritta sopra il problema si potrebbe risolvere in questo modo: si installa sul server a Roma un servizio OpenVPN, che avrà una certa porta (TCP o UDP) aperta in ascolto per connessioni da Internet. Noi a Tokyo installeremo sul nostro portatile sempre OpenVPN e lo configureremo per collegarci e autenticarci sul server. A questo punto, sia sul server che sul portatile, OpenVPN crea delle interfacce di rete virtuali (di tipo TUN o TAP, poi parleremo delle differenze), che possiamo pensare come delle interfacce virtuali che simulano la presenza di un cavo da Tokyo al server di Roma, che collega direttamente i due computer.
Ma allora a questo punto possiamo fare lo stesso su ciascuno dei computer dell’ufficio di Milano, e avremo una rete VPN al completo: 11 client e 1 server centrale. Potrebbero esserci soluzioni più furbe come installare OpenVPN solo sul router dell’ufficio di milano e poi aggiungere regole di route particolari sul server, ma qui analizzeremo solo un caso molto semplice.
Poiché la VPN emula l’esistenza di un “cavo”, possiamo utilizzare qualunque indirizzo e protocollo su queste interfacce. Tipicamente (per scarsità di indirizzi pubblici), all’interno della VPN utilizzeremo IPv4 privati.
Potremmo stabilire che ad esempio il server abbia un indirizzo virtuale 10.0.0.1 all’interno della VPN e che il client di Tokyo sia 10.0.0.2, mentre i computer di Milano siano da 10.0.0.3 a 10.0.0.12 . Una volta configurato tutto quindi, anche se siamo a Tokyo, possiamo agilmente accedere a uno dei computer dell’ufficio utilizzandone l’indirizzo privato della VPN. Qualcuno potrebbe chiedersi se ne valga davvero la pena: non era meglio solo esporre su internet i computer dell’ufficio? Lasciando perdere il fatto che sarebbero stati più sprotetti dall’esterno, bisogna tenere conto che OpenVPN non solo crea una rete virtuale, ma ci permette di far viaggiare sopra i dati cifrati. Per questo motivo possiamo stare molto tranquilli quando siamo dentro la nostra VPN.
Ad esempio: anche se siamo a Tokyo e copiamo documenti segreti nell’ufficio di Milano, i dati trasmessi non transiteranno “in chiaro” su Internet, ma verranno cifrati da Tokyo a Roma (fino al server) e poi anche da Roma fino a Milano (al computer interessato). Dunque i dati resteranno cifrati per tutta la durata del loro trasporto e sarà quindi un po’ come ad essere dietro la protezione del router nell’ufficio. Il giorno che volessimo aprire un altro ufficio a Tokyo sappiamo che grazie a OpenVPN, collegando tutti i computer di Tokyo al server di Roma, sarà come avere i due uffici collegati direttamente insieme in una LAN (Local Area Network).
Un altro utilizzo molto interessante della VPN è per redirigere tutto il traffico in uscita dal proprio computer. Facciamo un esempio: sempre parlando del caso di prima, potremmo essere interessati a far viaggiare non solo certe informazioni cifrate, ma bensì tutto il nostro traffico di Internet cifrato mentre siamo a Tokyo. Ovviamente non dobbiamo pensarlo cifrato “per sempre”, resta cifrato dal portatile fino a Roma, poi dal server di Roma in poi i dati escono da lì su Internet in chiaro. Potremmo non fidarci della connessione che stiamo usando a Tokyo perché potrebbe esserci qualcuno che sta “intercettando” i nostri dati che passano in chiaro sulla rete, questo potrebbe essere un buon motivo per fare quanto detto sopra.
Altra possibilità per volere ciò è che chi gestisce la connessione che stiamo usando a Tokyo abbia bloccato diverse porte in uscita e non ci permetta di utilizzare alcuni programmi (ad esempio le porte di IMAP o POP3 per la posta). Oppure ancora per qualche strano motivo vogliamo fare in modo di figurare come se ci stessimo collegando dall’Italia e non dal Giappone; per esempio per vedere alcuni video sul siti italiani, che sono visibili solo quando ci colleghiamo da un indirizzo IPv4 italiano. Dopo questa lunga introduzione sul perché vogliamo una VPN, vediamo come configurarla.

La configurazione

Per prima cosa assicuriamoci di avere installato OpenVPN sul nostro server e su tutti i client che vi si dovranno collegare. Esiste un pacchetto su praticamente tutte le distribuzioni GNU/Linux. Sul server assicuriamoci inoltre di avere installato anche OpenSSL, che ci servirà per i certificati di accesso.

Sicurezza e cifratura dei dati

OpenVPN permette di cifrare i dati trasmessi e l’autenticazione in tanti modi, quello che illustreremo qua è tra i più sicuri e controllabili. Tale metodo di cifratura e autenticazione si basa sull’utilizzo di una chiave pubblica (o certificato) e privata per ogni macchina collegata alla rete, insieme a un certificato di “autorità” (tra poco capirete di cosa si tratta).
L’idea di base è questa: il server centrale detiene una CA (Certificate Autority) che “firma” tutte le chiavi private dei vari computer, per garantire che sono autorizzate ad accedere alla rete. Il processo normalmente si divide in questo modo:

  • Il server genera una chiave per la sua CA e la “autofirma”
  • Ogni client della VPN genera una chiave privata.
  • Dalla chiave privata ogni client genera una richiesta di certificato.
  • Il client spedisce la richiesta di certificato al server.
  • Il server riceve la richiesta di certificato e la “firma”, generando un certificato per il client che ne aveva fatto richiesta.
  • Il server rimanda la richiesta di certificato al client.

Per riassumere ciascun client della rete dovrà essere in possesso della propria chiave privata, certificato firmato dalla CA e certificato della CA (quest’ultimo deve essere trasferito oltre alle altre operazioni dal server a ciascun client). In via teorica, se qualcuno vi “ruba” questi tre files potrebbe essere in grado di collegarsi alla vostra VPN. Se siete così paranoici (o forse la vostra paranoia è giustificata) sarebbe meglio impostare una password alla chiave privata, vedremo poi come farlo.
Questo processo deve essere eseguto in realtà anche dal server per generare una chiave privata e certificato per se stesso. Infatti anche il server avrà una sua chiave privata e certificato. Per la creazione di tutte le chiavi per un server ed un client si richiede normalmente l’esecuzione di 10 comandi di OpenSSL poco banali (escludendo poi i comandi per trasferire i file generati da una macchina all’altra). Per semplificare le cose esiste “easy-rsa”, un insieme di script che automatizza e semplifica in modo guidato la creazione di tutte le chiavi necessarie. Molti diffidano dall’uso di easy-rsa, poichè potrebbe comportare dei problemi di sicurezza. Infatti easy-rsa, per semplificare tutto il processo crea in un solo luogo tutte le chiavi pubbliche, private e CA per poi essere trasferite ai relativi host. Se qualcuno dovesse riuscire a intercettare le nostre comunicazioni mentre inviamo a ciascun client la sua chiave privata e pubblica potrebbe riuscire a collegarsi alla nostra rete. Se invece osserviamo il procedimento eseguito sopra, anche se i trasferimenti dei vari files avvengono in chiaro e sono intercettati, un eventuale attacante non potrà farsene nulla.
Infatti se osserviamo i punti del procedimento prima esposto passano in chiaro sulla rete solo: la richiesta di certificato, il certificato del client e il certificato della CA. Un attaccante con questi dati non potrebbe utilizzarli, poichè gli manca la chiave privata del client, che neanche il server conosce. Se utilizziamo invece easy-rsa dobbiamo inviare al client anche la sua chiave privata, quindi se la connessione viene compromessa un attaccante potrebbe collegarsi alla nostra rete. Per ovviare questo problema consiglio di eseguire tutti i trasferimenti dei certificati e chiavi usando una sessione SSH “trusted” (a cui ci siamo già collegati in passato e che quindi ci fornisce un “canale” di comunicazione cifrato affidabile).

Generazione delle chiavi

Dato che abbiamo deciso di usare easy-rsa, creiamo tutte le chiavi sul server. Spostiamoci sul server, assicuriamoci di essere root e per prima cosa copiamo gli script di easy-rsa (solitamente vengono automaticamente installati con il pacchetto di OpenVPN) dentro la cartella che utilizzeremo per OpenVPN:
mkdir /etc/openvpn/easy-rsa/
cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/ /etc/openvpn/easy-rsa/

Spostiamoci dunque nella cartella che abbiamo copiato e apriamo il file vars, che contiene delle variabili che saranno utilizzate per generare il certificato:
cd /etc/openvpn/easy-rsa/2.0/
nano -w vars

Nel file vedremo tutta una serie di variabili che saranno utilizzate per generare i vari certificati, tra queste ci sono variabili che impostano il nome dell’azienda, della città e altri dettagli che verranno messi di default sui certificati (per evitare di farvi compilare quei campi per ciascun certificato). Non sono campi necessari, se volete potete mettere NA nel caso non vogliate assegnare un valore.
Le due righe che vedrete:
CA_EXPIRE=3650
KEY_EXPIRE=3650

Indicano che i certificati e la CA generati avranno una durata massima di 3650 giorni, cioè di 10 anni. Questo significa che dopo 10 anni dalla generazione del certificato essi scadranno e non saranno più utilizzabili e dovranno essere ricreati. Se lo ritenete necessario potete modificare questi valori a vostro piacere, ricordate però di non far scadere mai la CA prima delle chiave, come numero di giorni.
La riga:
export KEY_SIZE=2048
Specifica la lunghezza dei certificati in bit. Il valore 2048 è solitamente più che appropiato, se siete paranoici in ambito di sicurezza potete però aumentarlo, anche a 4096 per esempio, questo richiederà però un po’ più tempo in seguito per il calcolo del DH e per l’autenticazione ogni volta.
Salviamo il file, chiudiamo nano e procediamo quindi a caricare tutte queste variabili definite e ripuliamo la directory dove metteremo le chiavi ( keys/ ):
source  ./vars
./clean-all

Passiamo ora a creare per prima cosa la CA e ad autofirmarla:
./build-ca
Compilate i campi necessari (in teoria dovrebbero essere tutti pre-compilati grazie al file vars compilato prima). Non riempite il campo che chiede per una password, vedremo dopo come proteggere le altre chiavi con password.
Proseguiamo ora creando una chiave privata e certificato (firmato dalla CA) per il server, come parametro del comando c’è il nome dei file che verranno generati generato:
./build-key-server VPN_Server
Quando viene chiesto se firmare il certificato rispondete ovviamente di sì.
A questo punto dobbiamo fare i certificati dei vari client che si dovranno collegare alla VPN. Possiamo scegliere se generare dei certificati protetti da password (va inserita ogni volta per poterli usare) o senza password. Solitamente la scelta dipende da quanto vi fidate dello “storage” dove terrete il certificato. Se il certificato non è protetto da password basta che ve lo copino (insieme alla CA etc..) per poter accedere alla vpn. Se è protetto da password invece serve una informazione in più per poterlo usare.
Nel caso decidiamo di generarlo senza password lanciamo:
./build-key client1
Con il parametro cambiato per ciascun client.
Se invece vogliamo un certificato protetto da password:
./build-key-pass client1
e poi inseriamo la password quando ci verrà richiesta (non quella nella compilazione dati del certificato!)
Attenzione! Assicuratevi di impostare un “Common name” diverso per ciascuno dei client, o avrete dei problemi!
Forse vi starete chiedendo perchè vengono utilizzati comandi diversi per generare alla fine sempre certificati e chiavi. Il fatto è che i certificati e chiavi del server saranno marcate in modo particolare come “certificati server”, di modo che quando i client si colleghereanno al server scambiandoci dati sapranno di comunicare con un certificato di tipo giusto.
Sarà necessario inoltre lanciare il seguente comando per generare il file per i parametri di scambio delle chiavi “Diffie-Hellman” necessario sul server che deve gestire le connessioni cifrate. Spiegare quello che fa è un po’ complicato, vi basti sapere che in questa parte devono essere calcolati dei numeri primi abbastanza grandi che serviranno come parametri per le connessioni cifrate. Il comando potrebbe impiegarci diversi minuti.
./build-dh
Un altro utile accorgimento di sicurezza è aggiungere un’altra chiave, questa volta statica (un po’ come una password ma in un file e molto lunga), da 1024 bit. Questa chiave viene utilizzata nella primissima fase di connessione con il server. È utile per prevenire attacchi “denial of service” sulla porta del server, ed autorizzare a passare al secondo passo di autenticazione solo a chi si presenta con questa chiave prima. La creeremo direttamente nella cartella dove già sono pronte tutte le altre chiavi e certificati.
cd keys/
openvpn -genkey -secret ta.key

Ora abbiamo tutte le chiavi e certificati che ci servono pronti in /etc/openvpn/easy-rsa/keys/.
A questo punto potete tenere lì tutto e per evitare confusioni è meglio creare una cartella /etc/openvpn/keys/ dove copiare le cose che servono solo al server.
mkdir -m 0700 /etc/openvpn/keys
cp dh2048.pem ta.key VPN_Server.crt VPN_Server.key ca.crt /etc/openvpn/keys/

Ovviamente i parametri di cp dipendono dai nomi che avete dato ai file del server. Se è andato tutto a buon fine ora avrete le chiavi e certificati del server in una cartella con accesso garantito in lettura, scrittura ed esecuzione solo a root.
Assicuratevi che anche la cartella delle chiavi in easy-rsa sia nella stessa condizione:
chmod -R 700 /etc/openvpn/easy-rsa/2.0/keys/
È meglio che sul server teniate tutti i certificati di tutti i client, perché il giorno che doveste decidere di revocare uno di questi certificati potrete farlo solo se ne siete in possesso. Vedremo tra poco come procedere eventualmente per la revoca.

Se non l’avete ancora fatto, questo è il momento per copiare tutte le chiavi e certificati ai vari client. Copiate i file utilizzando una connessione protetta (ad esempio tramite una sessione SSH “trusted”)! Per riassumere i file da copiare verso ogni client sono:

  • ca.crt
  • client1.crt
  • client1.key
  • ta.key

La configurazione del server OpenVPN

Avete spostato le varie chiavi sul server e copiate sui client, ora è il momento di preparare il file configurazione del server. Create un nuovo file /etc/openvpn/server.conf e iniziate a riempirlo seguendo la struttura di questo esempio:
######################################
port 1194
proto udp
dev tun
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/VPN_Server.crt
key /etc/openvpn/keys/VPN_Server.key
dh /etc/openvpn/keys/dh2048.pem
tls-auth /etc/openvpn/keys/ta.key 0
server 10.0.0.0 255.255.255.0
max-clients 10
ifconfig-pool-persist /etc/openvpn/ipp.txt
comp-lzo
keepalive 10 60
client-to-client
log-append /var/log/openvpn.log
status /var/log/openvpn-status.log
verb 4
######################################

Passeremo ora a commentare ogni riga sul suo significato, per chiarezza:

  • “port” specifica quale porta utilizzare, il conseguente parametro “proto” specifica se deve essere una connessione UDP o TCP. Giusto a scopo informativo vi ricordo che TCP è leggermente più lento di UDP poichè utilizza dei sistemi di verifica che ciascun pacchetto sia arrivato correttemente a destinazione, mentre UDP si limita a inviare il più velocemente possibile. Solitamente si consiglia sempre di usare UDP, salvo controindicazioni (che in realtà qualche volta ci sono), poichè il controllo di arrivo del pacchetto viene comunque fatto a livello software da TUN/TAP.
  • “dev TUN” specifica a OpenVPN di utilizzare una interfaccia virtuale di tipo TUNnel (virtualizza il passaggio di pacchetti IP), un’altra possibilità è di mettere TAP, che invece virtualizza tutto il protocollo Ethernet. Di solito si consiglia TUN poiché limita il numero di informazioni trasmesse, simulando un protocollo più ridotto. In alcuni casi, come ad esempio quando si vogliono mettere in bridge alcune interfacce di rete, è necessaria per forza TAP.
  • Le tre righe che cominciano con “ca”, “cert”, “key”, “dh” e “tls-auth” specificano il percorso dei relativi certificati e chiavi del server.
  • La riga “server 10.0.0.0 255.255.255.0 ” stabilisce quale rete e maschera di rete usare. In questo caso si specifica che sarà possibile usare tutti gli indirizzi tra 10.0.0.1 e 10.0.0.254. Solitamente il server si assegna in automatico il primo indirizzo libero. Eventualmente lanciate ifconfig in seguito per verificare quale indirizzio abbia preso.
  • “ max-clients 10” permette di impostare un numero massimo di client collegabili, è possibile ometterlo se non volete imporre limiti.
  • “ifconfig-pool-persist /etc/openvpn/ipp.txt” utilizza un file nella cartella di OpenVPN per memorizzare tutte le ultime assegnazioni di indirizzi e dare ai client sempre gli stessi ip (l’identificazione viene fatta in base all’hostname).
  • “comp-lzo” abilita la compressione dei dati trasmessi mediante algoritmo LZO.
  • “keepalive 10 60” invia dei messaggi di keepalive (una sorta di ping a basso livello) ogni 10 secondi ai client, se non rispondono entro 60 secondi vengono scollegati dal server.
  • “client-to-client” stabilisce che i client che si collegano alla VPN possono anche comunicare tra di loro. Senza questa opzione i client possono comunicare solo con il server ma non con gli altri collegati.
  • “log-append /var/log/openvpn.log” scrive tutti i log di OpenVPN in uno specifico file.
  • “status /var/log/openvpn-status.log” specifica quale file utilizzare per memorizzare eventuali informazioni di stato dei client collegati.
  • Infine “verb 4” è il livello di verbose standard per la stampa dei log. Solitamente per controllare eventuali problemi lo si alza fino a 7, in casi estremi fino a 9.

In teoria possiamo già provare se funziona tutto. Magari meglio commentare la riga che inizia con “log-append” per i test, così potremo vedere direttamente gli eventuali problemi senza stare ad aprire il file di log. Ricordate sempre di lanciare da root.
openvpn --config /etc/openvpn/server.conf --verb 4
Una curiosità che potrebbe interessarvi: in realtà è possibile dare tutti i parametri a openvpn, come dati nel file di configurazione, come parametri da terminale, semplicemente aggiungendo “–” davanti a ciascuno.
Se è tutto in ordine potete chiudere e rilanciare come demone (il seguente comando è valido sui sistemi debian-like):
/etc/init.d/openvpn restart
Ovviamente essendo un demone che rileva in automatico il file server.conf , ad ogni avvio la VPN partirà in automatico. Assicuratevi se sia questo ciò che volete.

La configurazione del client OpenVPN

Saltiamo ora alla configurazione del generico client. Supponiamo di aver già spostato le chiavi necessarie dal server e andiamo a creare /etc/OpenVPN/client.conf :
#################################################
client
dev tun
proto udp
remote SERVER_HOSTNAME 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client1.crt
key /etc/openvpn/client1.key
tls-auth /etc/openvpn/ta.key 1
keepalive 8 40
comp-lzo
verb 4
ns-cert-type server
#################################################

Molte opzioni si rispecchiano simili a quelle del server, vediamo le differenze:

  • “client” specifica che siamo su un client e che vogliamo accettare eventuali opzioni che ci invia il server tramite “push” e che vogliamo utilizzare autenticazione basata su TLS.
  • “dev tun” e “proto tcp” devono ovviamente rispecchiare quello che abbiamo messo sul server.
  • “remote SERVER_HOSTNAME 1194” specifica l’hostname o indirizzo IP del server a cui collegarsi e la porta.
  • “resolv-retry infinite” significa che se fallisce la risoluzione dell’hostname del server per qualche motivo, OpenVPN continua a tentare all’infinito di risolverlo. Può sembrare stupido ma vedremo poi che invece per vari motivi può tornare molto comodo.
  • “nobind” è una opzione che specifica al client di utilizzare in ascolto una porta qualunque. È un dettaglio molto specifico, possiamo tranquillamente ignorarlo o anche omettere di scriverlo nel file.
  • “persist-tun” indica a OpenVPN di non distruggere l’interfaccia virtuale quando deve riavviarsi (nonostante il nome ingannevole, questa opzione è valida sia per interfacce TUN che per interfacce TAP), mentre “persist-key” indica di non ricaricare le chiavi quando riavvia la connessione a causa di keepalive.
  • “tls-auth” ha questa volta parametro 1 e non 0 dopo il path del file, poiché viene usato dal lato client.
  • “keepalive 8 40” come sul server, invia un messaggio di ping ogni 8 secondi quando non c’è attività sull’interfaccia. Se il server non risponde entro 40 secondi viene riavviato OpenVPN.
  • “ns-cert-type server” serve a verificare che il server remoto utilizzi effettivamente un certificato marcato come “server”. Questo serve a prevenire attacchi man-in-the-middle in cui un attaccante potrebbe fingersi server usando un certificato client valido.

Ora, come per il server possiamo avviare il servizio o tutto manualmente:
openvpn --config /etc/openvpn/client.conf
Per testing si possono mandare un po’ di ping al server (che non deve essere impostato per bloccarli ovviamente…)
ping 10.0.0.1
A questo punto la vostra rete dovrebbe essere pronta, se volete lanciate direttamente il demone:
/etc/init.d/openvpn restart

Uscire su internet tramite il server della VPN

Per prima cosa andiamo sul server (da root) e abilitiamo il forwarding dei pacchetti e il mascheramento dell’indirizzo in NAT (masquerade):
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
iptables -P FORWARD DROP
iptables -A FORWARD -s 10.0.0.0/24 -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT

Con la prima riga abilitiamo la funzione di forwarding dei pacchetti IP all’interno del nostro server, quindi con la seconda riga creiamo il NAT e con le righe seguenti abilitiamo la possibilità di forwarding solo per i pacchetti che ci interessano: permetteiamo a pacchetti che arrivano dalla VPN di essere forwardati ovunque, mentre permettiamo a pacchetti provenienti da ovunque di essere diretti verso la VPN solo se fanno parte di connessioni già stabilite.

Poi spostiamoci sul client e cambiamo la sua configurazione.
Dobbiamo aggiungere la riga
redirect-gateway
che sostanzialmente dice al client di fare questo: crea una regola di routing statica di modo da restare collegato al server della VPN mediante il gateway default attuale, poi cancella il routing del gateway default e aggiungi un nuovo gateway di default.
Se stiamo usando TUN allora OpenVPN riesce a trovare da solo quale gateway di default impostare (in realtà passa tramite l’indirizzo point-to-point), se usiamo TAP invece dovremo specificare ad esempio di usare 10.0.0.1 come gateway con il parametro:
route-gateway 10.0.0.1
In realtà è spesso consigliabile sostituire il comando “redirect-gateway” con “redirect-gateway def1”,che non cancella la regola di default esistente ma ne aggiunge due nuove (una da 0.0.0.0 a 127.255.255.255 e un’altra da 128.0.0.0 a 255.255.255.255). Questo risolve alcuni problemi per le connessioni già stabilite o quando su alcune reti cambia in continuazione il gateway.

In ogni caso, dobbiamo prestare attenzione ai DNS. Se il nostro computer già utilizza dei DNS pubblici (ex: 8.8.8.8) non dobbiamo preoccuparci, mentre se ad esempio usiamo come server DNS il router interno alla nostra rete (192.168.0.1 o roba del nostro ISP), una volta cambiate le regole di routing non riusciremo più a raggiungerlo.
Uno dei tanti modi per risolvere questo problema è creare due script che cambiano i server DNS nel momento in cui avviamo la VPN. Per evitare conflitti e per comodità installiamo il programma “resolvconf” sulla nostra distribuzione e creiamo ad esempio il file /usr/bin/dnsvpnsu con questo contenuto:
#!/bin/bash
echo "nameserver 208.67.222.222" | resolvconf -a tun0

Che una volta eseguito aggiungerà come server DNS primario OpenDNS. Un altro dei server DNS mondiali più famosi, di Google, è 8.8.8.8
Creiamo poi un altro file /usr/bin/dnsvpngiu 
#!/bin/bash
resolvconf -d tun0

Che cancellerà il server DNS aggiunto dalla vpn quando la scolleghiamo.
Diamo quindi i permessi di esecuzione a questi due script:
chmod +x /usr/bin/dnsvpnsu
chmod +x /usr/bin/dnsvpngiu

E a questo punto torniamo nel nostro file di configurazione del client della vpn e aggiungiamo alla fine i comandi per lanciare questi due script rispettivamente all’avvio e all’arresto della vpn:
script-security 2
up /usr/bin/dnsvpnsu
down /usr/bin/dnsvpngiu

La prima riga è legata ad una serie di politiche di sicurezza di openvpn, se vogliamo eseguire degli script all’avvio o all’arresto dobbiamo impostare il livello di sicurezza script a 2.

Rendere le regole di iptables persistenti

Abbiamo visto che per uscire su Internet tramite la VPN abbiamo abilitato la funzionalità di forwarding e impostato alcune regole iptables. Al riavvio del sistema entrambe le cose verranno “resettate”, quindi come rendere il tutto persistente? Una soluzione stupida e semplice è utilizzare /etc/rc.local e iptables-save.

Per prima cosa salviamo la nostra attuale configurazione di regole per iptables con il comando iptables-save in un file.
iptables-save > /root/firewall_rules
In questo modo iptables effettua un dump della configurazione attuale nel file di testo /root/firewall_rules, e sarà sufficiente invocare il comando iptables-restore per reimpostare le stesse regole. Come farlo all’avvio?

Aprite il file /etc/rc.local e inserite le due righe seguenti alla fine (o prima di un eventuale riga “exit 0” già presente):
echo 1 > /proc/sys/net/ipv4/ip_forward

iptables-restore < /root/firewall_rules
Con la prima riga riabilitiamo la funzionalità di routing/forwarding dei pacchetti all’interno del kernel Linux, la seconda riga invece apre il file che abbiamo salvato prima e riapplica le regole iptables che abbiamo salvato. Questo sarà fatto ad ogni avvio del sistema come ultimo passo prima del login.

 

Kung-fu degli IP e delle porte di rete

Può capitare che siamo su un client della VPN che ha bisogno di esporre su internet un servizio, come un server web o qualcosa d’altro, però si trova dietro la NAT che abbiamo creato prima. Un’ interessante modifica alla VPN potrebbe essere quella di aggiungere sul server VPN una regola che rediriga il traffico in ingresso da una certa porta TCP/UDP ad un’altra porta TCP/UDP di un client della VPN. Per fare ciò ci basta aggiungere sul server qualcosa del tipo:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 6001 -j DNAT --to-destination 10.0.0.2:22
iptables -A FORWARD -o tun0 -d 10.0.0.22 -p tcp --dport 22 -j ACCEPT

Che redirige il traffico in ingresso sulla porta TCP 6001 del server alla porta 22 dell’host 10.0.0.2 della VPN. Il secondo comando iptables serve invece per abilitare il forward dei pacchetti verso quella porta dell’host interno alla vpn. Su alcuni server può capitare anche di avere più indirizzi IP, perché ad esempio lo stesso server ha diverse interfacce di rete, ciascuna con un proprio IP pubblico. Potrebbe essere molto utile che un certo client della rete VPN utilizzi uno degli IP pubblici del server per se stesso, di modo da avere un IP pubblico ovunque si trovi e risultare praticamente come se fosse senza NAT.

Per fare questo dovremo aggiungere tre regole di iptables sul server:
iptables -t nat -A PREROUTING -d 123.45.6.7/32 -i eth0 -j DNAT --to-destination 10.0.0.2
iptables -t nat -A POSTROUTING -s 10.0.0.2/32 -o eth0 -j SNAT --to-source 123.45.6.7
iptables -A FORWARD -o tun0 -d 10.0.0.2 -j ACCEPT

Dove 123.45.6.7 è l’indirizzo IP che vogliamo reindirizzare e 10.0.0.2 è l’host della VPN a cui reindirizzarlo. È sottointeso che l’host della VPN su cui facciamo questa operazione deve per forza uscire su internet tramite il server della VPN.

 

Utilizzare OpenVPN dietro proxy

Può essere che qualche client della rete si trovi per qualche motivo dietro a un proxy, come accade spesso in molte aziende. Per collegarci basterà specificare due opzioni aggiuntive nel file di configurazione del client:
http-proxy PROXY_HOSTNAME 8080
http-proxy-retry

La revoca dei certificati

La vostra configurazione funziona perfettamente, però avete appena scoperto che un certificato ha la sicurezza compromessa (è stato rubato, è stato perso). Non volete assolutamente che nessuno in possesso di quel certificato riesca a fare nulla, quindi decidete di revocarlo. Ovviamente avete ancora il certificato nella vostra cartella di easy-rsa sul server, quindi entrateci:
cd /etc/openvpn/easy-rsa/2.0/
source  ./vars
./revoke-full client1

Usciranno una serie di messaggi, alla fine vedrete “error 23”, significa che la revoca è state effettuata con successo. Vedrete un nuovo file keys/crl.pem che contiene l’elenco dei certificati revocati.
Ora dovrete copiare il file nella cartella principale del server:
cp keys/crl.pem /etc/openvpn/crl.pem
E quindi dovrete aggiungere una riga nel file di configurazione del server, se non l’avevate già messa:
crl-verify /etc/openvpn/crl.pem
Se avevate già aggiunto questa riga in precedenza e volete comunque “rinfrescare” la configurazione del server, per avvertirlo di non accettare le connessioni da quel client, potete lanciare (sui sistemi debian-like):
/etc/init.d/openvpn reload
Questo comando rinfresca la configurazione, nessuno dei client si accorgerà di nulla, tranne il client revocato ovviamente.

Un modo un po’ più sicuro di generare certificati

Come già detto prima, non è proprio la cosa migliore in fatto di sicurezza quella di generare chiavi pubbliche e private insieme, perchè se nel loro transito dal server a uno dei client venissero entrambe intercettate da un attaccante, questo potrebbe sfruttarle a suo favore per collegarsi alla rete. Tutto questo ipotizzando che siano chiavi non protette da password, ma anche se lo fossero potrebbe restare un po’ di margine per tentare degli attacchi a forza bruta e la cosa non ci piace. Questo è il motivo per cui se si procede il quel modo bisogna essere assolutamente certi di trasferire le chiavi su un canale sicuro.
Vediamo allora ora come riuscire a spostare comunque in modo sicuro le chiavi pur usando easy-rsa.
Ci spostiamo su uno dei client e generiamo la sua chiave privata nella cartella di openvpn:
openssl genrsa -out client1.key 1024
Se vogliamo utilizzare chiavi di dimensioni diverse basta cambiare ovviamente l’ultimo parametro. A questo punto generiamo la “richiesta di certificato” che invieremo al server tranquillamente anche se su un canale non sicuro.
openssl req -new -key client1.key -out client1.csr
A questo punto copiamo in qualche modo il file generato client1.csr nella cartella keys/ di easy-rsa sul server e spostiamoci nella cartella principale di easy-rsa, dove ci basterà lanciare:
./sign-req client1
E dopo una conferma il server utilizzerà la CA per creare un certificato valido a partire dalla nostra richiesta. Probabilmente uscirà un errore di chmod a fine operazione perché non è presente la chiave privata (e non vogliamo che ci sia!), ma possiamo ignorarlo tranquillamente.
A questo punto andiamo nella cartella keys/ di easy-rsa, recuperiamo il certificato generato che si chiamerà ovviamente client1.crt e spostiamolo sul nostro client. A questo punto il nostro client avrà sia chiave pubblica che privata e anche se ci fosse stato un eventuale attaccante a intercettare il traffico, non potrà farsene nulla dei dati ricavati, poichè gli manca la chiave privata, che non conosce.

Pubblicità


24 Responses to “Guida a OpenVPN per GNU/Linux”

  1. Ottimo Lavoro!

  2. 2 Siv

    Domanda che non c’entra nulla: cosa usi per quotare il codice? 🙂

  3. 4 Siv

    … però “rinfresca” è veramente triste…

  4. In effetti rinfresca è un po’ triste, comunque ho già trovato roba da aggiungere (firma di richieste di certificato con easy-rsa), appena posso aggiungo.

  5. 6 Eugenio

    Ottima spiegazione. Bravo.
    Ho una domanda: dal server OpenVPN esiste una riga di comando (OS Linux) che mi permetta di disconnettere un client specifico senza dover riavviare tutto quanto?

    • Non che io sappia. Però se il client si sta collegando tramite un certificato è possibile revocarlo e quindi fare il “reload” con
      /etc/init.d/openvpn reload
      che lo scollegherà dalla rete senza staccare gli altri.

      • 8 Eugenio

        Capito, però il mio problema è che il client si collega da remoto tramite GPRS (non sto a scendere nei dettagli). Più che altro non è tra le opzioni possibili della OpenVPN dei client.
        Mi sa che mi accontenterò di riavviare direttamente il server, a scapito della mancata comunicazione per qualche minuto degli altri client.

        Grazie lo stesso.

  6. Ho aggiunto qualche riga alla fine su come trasferire certificati in modo più sicuro.

  7. 10 Pol

    bello ‘sto howto! 🙂 grande!

    ho rispolverato un pò il passato..

    Pol

  8. 11 Carlo

    Visto che chiedi se vi sono errori mi permetto…
    anzitutto alterni durante tutto l’articolo OpenVPN e openvpn come nome della cartella in /etc/ (quello corretto è openvpn)
    poi ad un certo punto dici di dare ../vars ma il comando giusto è source ./vars

    A parte questi dettagli non posso che ringraziarti! una guida fatta molto molto bene e completa! non sai quando l’ho desiderata prima di trovarla!

    • 12 Carlo

      anche nella configurazine del client persist-TUN è sbagliato e va sostituito con persist-tun
      🙂
      grazie

    • Grazie mille per la segnalazione!
      Ho fatto qualche casino quando ho utilizzato un Search & Replace per sistemare alcune parole (pessima idea!) 😀
      Ora sistemo, ciao!

  9. 14 Max

    Ciao!Devo dire che la guida è fatta veramente bene,ma ho un problema

    Avrei bisogno di crittografare tutto il traffico web tramite la vpn,ho seguito i tuoi consigli ma nulla il client non naviga ma è correttamente connesso alla vpn,ti spiego la mia situazione:

    client esterno connesso con rete 3g—>Internet—>server vpn(10.8.0.1) che utilizza i dns di opendns per navigare

    Come mai?Ho provato in tutti i modi

    • Per il dns hai usato
      dhcp-option DNS INDIRIZZO_IP_DNS_SERVER
      ?
      So che ci sono alcuni problemi con questa configurazione. Prova a impostare dns statici su ciascun client della vpn…
      Non saprei che altro dirti di provare

  10. 16 lorenzo

    Fantastica guida!!!! Complimenti

    lorenzo

  11. 17 Lorenzo

    Gran bella guida sarei interessato a provarla ma non ho a disposizione nessun server personale…sapresti consigliarmi qualcosa a basso costo o meglio gratis..thanks

  12. 19 Edoardo

    Ciao una domanda: avrei bisogno che un client della vpn, una volta connesso si colleghi solo ad una determinata macchina della rete. e non deve vedere invece tutta la rete. coma faccio?

    grazie

  13. 20 Alberto

    Sei un grande! Con la tua guida mi hai risolto la giornata!!!

  14. Bravo Otacon, ogni tanto ripasso da qui a rileggere la guida, è la più completa che abbia trovato in giro! Quand’è che gli fai un restyling?

  15. Molto interessante, grazie.


  1. 1 HowTo: Costruirsi la propria rete VPN « Otacon22 blog
  2. 2 Guida a OpenVPN per GNU/Linux « DiAbOlIkO NetWork

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...


%d blogger hanno fatto clic su Mi Piace per questo: