OpenVPN: connessione sicura attraverso Internet di molti client ad un server

VPN significa, letteralmente Rete Privata Virtuale, cioè una serie di collegamenti virtuali e privati creati su un’infrastruttura ad accesso pubblico, come ad esempio Internet. Una rete privata virtuale consente di comunicare in maniera sicura attraverso un canale insicuro in una forma efficiente ed economica.

In questo articolo vedremo come creare un server VPN a cui far collegare diversi client, con l’obiettivo di creare una rete estesa e sicura. Il tutto verrà realizzato mediante il celebre software opensource OpenVPN.

Un po’ di teoria

Prima di incominciare con la parte pratica, vediamo quali sono i concetti di base di una VPN.

L’esigenza alla base di una VPN è quella di creare un canale di comunicazione sicuro tra diversi soggetti, appoggiandosi ad un’infrastruttura già esistente, in modo da poter scambiare i propri dati come se si fosse connessi ad una grande rete LAN senza affrontare i costi altissimi per l’installazione di un’infrastruttura fisica tra diverse sedi.

Seguendo l’analogia che rappresenta Internet come un sistema idraulico, si può pensare ad una VPN come un “tubo dentro ad un tubo”.

Tipologie di VPN

Esistono innumerevoli tipi di tecnologie per la creazione di VPN che differiscono per diversi fattori, come ad esempio:

  • I protocolli usati per creare i tunnel privati sulla rete sottostante;
  • La posizione degli endpoint dei tunnel;
  • Il livello di sicurezza fornito;
  • Il livello OSI usato per l’interconnessione delle diverse reti;

Attualmente vengono identificati tre tipologie principali di VPN:

  • Trusted VPN
  • Secured VPN
  • Hybrid VPN

Le VPN di tipo ‘Trusted’ sono state le prime ad essere create e sono ancora in uso in alcuni ambienti come quelli bancari, si tratta di reti virtuali create a partire dall’hardware di rete: in questo caso esiste un ISP (Internet Service Provider) che stabilisce indirizzi e politiche di routing per il proprio cliente, creando così una vera e propria rete virtuale sulla propria infrastruttura. Il grosso vantaggio che forniscono queste reti è il fatto che il traffico viaggia su percorsi ben definiti ed è possibile stabilire in maniera molto semplice politiche di QoS (la qualità del servizio offerto dalla rete), anche se è necessario sacrificare un po’ di flessibilità.

Le VPN di tipo ‘Secured’ invece prevedono che il traffico venga incanalato su tunnel cifrati e spedito attraverso Internet come se fosse normale traffico. Nel caso in cui uno di questi pacchetti finisca nelle proverbiali mani sbagliate, le informazioni in esso contenute saranno comunque inaccessibili. Lo svantaggio rispetto alle trusted VPN è la mancanza di predeterminazione dei percorsi effettuati dai pacchetti.

L’ultima tipologia di VPN è, come suggerisce il nome, un mix tra le due tipologie precedenti, prendendo la sicurezza intrinseca nata dalla cifratura di tutto il traffico di rete delle Secured VPN e la possibilità di fare QoS in maniera semplice, tipica delle Trusted VPN.

OpenVPN permette di creare proprio Secured VPN.

Installazione

Giungiamo così alla parte più pratica dell’articolo, l’installazione e configurazione del servizio OpenVPN. L’articolo tratta l’installazione del software su un sistema operativo Debian Lenny, ma a pacchetti installati, le informazioni sono utilizzabili sulle più diffuse distribuzioni.

Verrà assunto inoltre che il router con il quale si accede ad internet permetta di fare l’apertura della porta 1194 TCP (e anche UDP se possibile) verso il vostro server.

Il primo step è naturalmente quello di installare openvpn:

# aptitude install openvpn

Una volta installati i vari pacchetti, siamo pronti per sporcarci le mani.

Generazione dei certificati

Per la cifratura dei pacchetti OpenVPN usa il protocollo SSL, e per tanto è necessario generare tutta la serie di certificati per permettere sia la cifratura della connessione che l’autenticazione dei vari client.

Fortunatamente il pacchetto di OpenVPN fornisce una serie di script già pronti atti a tale scopo nel path /usr/share/doc/openvpn/examples/easy-rsa/2.0/:

# ls /usr/share/doc/openvpn/examples/easy-rsa/2.0/
build-ca          build-key-server  Makefile              sign-req
build-dh          build-req         openssl-0.9.6.cnf.gz  vars
build-inter       build-req-pass    openssl.cnf           whichopensslcnf
build-key         clean-all         pkitool
build-key-pass    inherit-inter     README.gz
build-key-pkcs12  list-crl          revoke-full

Nulla vieta di lasciare gli script li dove sono e copiare solo i file generati nella directory di configurazione di OpenVPN, io per comodità preferisco spostare tutta la directory sotto /etc/openvpn/easy-rsa/.

# cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/ /etc/openvpn/easy-rsa
# cd /etc/openvpn/easy-rsa

Tra i vari file potrete notare un file di testo chiamato “vars”, è un file che contiene tutte le variabili necessarie agli script di generazione di certificati e chiavi.
Sebbene non sia necessario modificare i parametri preimpostati (poichè possono essere sovrascritti durante l’esecuzione dei vari script) risulta più comodo in caso di generazione di un gran numero di certificati.

I parametri da modificare sono i seguenti:

  • KEY_SIZE
  • KEY_COUNTRY
  • KEY_PROVINCE
  • KEY_CITY
  • KEY_ORG
  • KEY_EMAIL

Sono parametri abbastanza auto esplicativi, ecco come si presenta il mio file vars:

export KEY_SIZE=2048
...
export KEY_COUNTRY="IT"
export KEY_PROVINCE="IT"
export KEY_CITY="Milano"
export KEY_ORG="VostraAzienda"
export KEY_EMAIL="my-email@vostraazienda.it"

A questo punto siamo pronti per generare la nostra certificate authority, ossia la componente (auto generata) che validerà i certificati per la comunicazione, ed i certificati stessi.
Prima di tutto dobbiamo fare in modo di esportare tutto ciò che è contenuto dentro al file ‘vars’ appena modificato:

# source vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys
# ./clean-all

È necessario richiamare anche lo script “clean-all” per avere la certezza di partire con un ambiente pulito.

Ora possiamo generare la nostra Certificate Authority:

# ./build-ca
Generating a 1024 bit RSA private key
..................................................++++++
...++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [IT]:
State or Province Name (full name) [IT]:
Locality Name (eg, city) [Milano]:
Organization Name (eg, company) [VostraAzienda]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [VostraAzienda CA]:
Email Address [my-email@vostraazienda.it]:

Alla richiesta di input mi sono limitato semplicemente a premere invio, i dati erano già corretti poichè sono stati modificati nel file ‘vars’.
Ora possiamo creare il certificato per il server VPN:

# ./build-key-server Gateway

Gateway è il nome della macchina su cui sto installando il server VPN, per coerenza la coppia chiave/certificato avrà il nome dell’host su cui viene usato. Vediamo l’esecuzione dello script:

Generating a 1024 bit RSA private key
..................++++++
.++++++
writing new private key to 'Gateway.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [IT]:
State or Province Name (full name) [IT]:
Locality Name (eg, city) [Milano]:
Organization Name (eg, company) [VostraAzienda]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [Gateway]:
Email Address [me@myhost.mydomain]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:password
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'IT'
stateOrProvinceName   :PRINTABLE:'IT'
localityName          :PRINTABLE:'Milano'
organizationName      :PRINTABLE:'VostraAzienda'
commonName            :PRINTABLE:'Gateway'
emailAddress          :IA5STRING:'my-email@vostraazienda.it'
Certificate is to be certified until Apr 25 13:50:00 2020 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Quando lo script chiede una password è lecito premere semplicemente invio per evitare di dover immettere la password ogni (ri)avvio di OpenVPN.

Generiamo ora il file Diffie-Hellman, necessario per l’avvio delle connessioni cifrate.
Attenzione, è un’operazione MOLTO lunga, quindi preparatevi a prendervi un paio di caffè…

# ./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
........+............

Dopo la vostra ristorante pausa caffè, passiamo a generare l’ultima chiave necessaria per l’instaurazione di una connessione sicura, questa chiave dovrà essere copiata anche su tutti i client.

# openvpn --genkey --secret keys/ta.key

Generazione dei certificati per i client

La generazione del certificato per il client è letteralmente identica alla generazione di un certificato per il server.
Personalmente preferisco generare dei certificati nominali:

# ./build-key fpedrini

e seguirà una procedura identica a quella della generazione del certificato per il server.

Configurazione del server

Passiamo ora configurazione vera e propria del demone di OpenVPN.
Anche in questo caso il pacchetto debian ci viene in aiuto con un file di configurazione già precotto e adatto ai nostri scopi, dobbiamo solo aggiustare qualche piccolo parametro.

Innanzitutto è necessario copiare il file di esempio nella directory giusta:

# cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
# cd /etc/openvpn
# gunzip server.conf.gz

Ora siamo pronti a modificare la configurazione, per brevità citerò solo le direttive che andremo a toccare:

local 192.168.0.1
port 1194
proto udp

Queste direttiva indicano ad OpenVPN rispettivamente:

  • Su quale indirizzo ip locale mettersi in attesa di connessioni, se omessa il demone userà tutte le interfacce
  • Su quale porta ascoltare, la 1194 è il default
  • Che tipo di protocollo utilizzare per il tunnel, le possibilità sono ‘TCP’ e ‘UDP’, vedremo più avanti le differenze
dev tun

Indica a OpenVPN di creare un tunnel al layer 3 del livello OSI, utilizzando ‘tap’ invece, andremmo a creare un bridge di rete a livello 2.

ca easy-rsa/keys/ca.crt
cert easy-rsa/keys/Gateway.crt
key easy-rsa/keys/Gateway.key  # This file should be kept secret
dh easy-rsa/keys/dh2048.pem

Queste direttive invece indicano al demone dove andare a prendere i file relativi alla Certification Authority, al certificato del server e il file Diffie-Hellman.

server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.1.0 255.255.255.0"

Questi parametri stabiliscono:

  • la subnet e la maschera della rete della VPN, il server prenderà automaticamente il primo indirizzo
  • il file in cui salvare la lista degli ip assegnati dal dhcp interno di OpenVPN
  • la rotta che il server deve comunicare al client per fare in modo che possano raggiungere la rete dietro alla VPN.
;push "redirect-gateway def1 bypass-dhcp"

Questa riga fa in modo che tutto il traffico generato dai client passi attraverso la VPN. Non sempre è consigliabile attivare questa opzione, poichè causa un notevole rallentamento nella connessione dei client dal momento che i pacchetti del traffico “normale” dovranno transitare sulla VPN prima di poter uscire su internet.
Nella mia configurazione è stata lasciata commentata.

push "dhcp-option DNS 192.168.1.1"
push "dhcp-option DNS 208.67.220.220"
push "dhcp-option WINS 192.168.1.3"

Le prime tre righe permettono di forzare i server DNS e i server WINS tramite il DHCP interno di OpenVPN, mentre l’ultima permette ai client di comunicare tra di loro.

keepalive 10 120

Il keepalive di OpenVPN permette di tenere vive le sessioni che passano attraverso i firewall, il primo parametro stabilisce ogni quanti secondi mandare un messaggio verso il client (è qualcosa di simile ad un ping ICMP), il secondo invece stabilisce il periodo massimo di inattività di una connessione.

tls-auth keys/ta.key 0

È il file necessario per la creazione della connessione cifrata, il secondo parametro settato a 0 indica che la chiave sta venendo usata dal server, mentre sui client sarà impostato a 1.

log-append  /var/log/openvpn/openvpn.log
verb 3

E per concludere i parametri dedicati al logging, che sono abbastanza auto esplicativi. Il livello di verbosità può variare da 1 a 20.

Per testare rapidamente la configurazione è sufficiente lanciare direttamente OpenVPN (assicurandosi prima di aver fermato il demone lanciato dall’init script durante l’installazione):

# invoke-rc.d openvpn stop
Stopping virtual private network daemon: server.
# openvpn server.conf

Se non ricevete nessun errore allora la vostra configurazione è corretta, potete interrompere l’esecuzione con Ctrl+C.

Come ultima cosa è necessario configurare il file /etc/default/openvpn per permettere l’avvio automatico del demone in fase di boot:

...
...
AUTOSTART="server"
...
...

La riga fondamentale è AUTOSTART=”server”, che permette all’initscript di far partire il demone usando la configurazione “server”, quella da noi creata.

Configurazione di IPTables

Per consentire ai pacchetti che viaggiano sulla vpn di passare sulla rete vera è necessario abilitare il forwarding tramite iptables, con due semplici regolette:

iptables -A INPUT -i tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -j ACCEPT

e ovviamente attivare il forward con

sysctl -w net.ipv4.ip_forward=1

Configurazione dei client

La configurazione dei client è abbastanza rapida, innanzitutto vediamo cosa serve per un client:

  • La coppia certificato/chiave per il client (i due file .key e .crt)
  • Il certificato della CA del server (il file ca.crt)
  • La chiave di autenticazione TLS (il file ta.key)
  • Il file di configurazione per il client.

I primi tre pezzettini li possiamo recuperare tranquillamente dal server, li abbiamo generati nei passi precedenti, vediamo ora la struttura del file di configurazione:

client

Specifica che si tratta appunto di un client 🙂

dev tun
proto udp

queste righe specificano rispettivamente che stiamo creando una connessione a livello IP e che ci vogliamo connettere usando un tunnel UDP,
Ovviamente questi dati devono coincidere con le impostazioni lato server

remote mightyvpn.vostraazienda.it 1194

l’hostname e la porta a quale connettersi, anche in questo caso la porta deve coincidere con quella specificata nella configurazione del server.
È possibile specificare più server remoti, nel caso in cui uno di essi sia inattivo, OpenVPN passerà al successivo.

resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun

Queste direttive stabiliscono che:

  • Il client OpenVPN dovrà tentare all’infinito di risolvere il nome del server (ovviamente è utile solo se come remote server si specifica un nome e non un indirizzo IP)
  • Il client non deve fare ‘bind’ su una porta specifica
  • Il client deve fare “privilege dropping” dopo l’inizializzazione (inutile su sistemi windows)
  • Il client deve tentare di rendere persistenti il tunnel
ca ca.crt
cert fpedrini.crt
key fpedrini.key
ns-cert-type server
tls-auth ta.key 1

Ed infine questi sono i parametri relativi ai certificati. Come potete vedere la configurazione è identica al lato server, con l’eccezione della riga ‘tls-auth’, che finisce per “1”.

Una volta salvato il file di configurazione come ‘/etc/openvpn/client.conf’ e affiancato da tutti i vari file a corredo è possibile avviare la connessione ad OpenVPN.

Analogamente a quanto fatto per il server, è possibile fare in modo che il proprio pc avvii la connessione all’avvio del demone OpenVPN modificando opportunamente il file /etc/default/openvpn:

...
...
AUTOSTART="client"
...
...

Conclusioni

Il test principale di funzionamento è quanto di più banale possa esserci: vedere cioè se dai client che si connettono alla rete si riesce ad accedere a computer presenti nella sotto rete, controllando servizi che si conosce come attivi o attraverso banali ping.
In pochi passi un’intera infrastruttura può essere accessibile ovunque, grazie ad OpenVPN!

11 risposte a “OpenVPN: connessione sicura attraverso Internet di molti client ad un server”

  1. Avatar paolo
    paolo

    ciao, ottima guida! volevo solo sapere se era possibile creare una coonfigurazione client da porter passare a tutti i futuri utenti che abbia al suo interno già tutte le chiavi e certificati, in modo tale che si copino tutta la directory in /opt/openvpn… grazie

  2. Avatar Francesco Pedrini

    Ciao Paolo, grazie! 🙂

    Per quanto riguarda la tua domanda, quando installo un server OpenVPN, dopo aver generato tutti i certificati uso questo semplice script:

    cat user_list | while read a; 
    do 
    	mkdir $a
    	cp /etc/openvpn/easy-rsa/$a.* $a/
    	cp /etc/openvpn/easy-rsa/ta.key $a/
    	cp /etc/openvpn/easy-rsa/ca.crt $a/
    	cp /etc/openvpn/client.conf.template $a/client.conf
    	sed "s/REPLACEME/$a/" $a/client.conf
     done
    

    queste poche righe prendono la lista degli utenti all’interno del file “user_list”, crea una directory per ogni utente, copia i vari certificati, chiavi e un file di configurazione tratto da un template (identico al file di configurazione finale con l’unica differenza di avere la stringa “REPLACEME” al posto del nome utente), ed effettua le modifiche necessarie al file di conf.

    Alla fine dell’esecuzione dello script, troverai nella directory da cui hai lanciato lo script una serie di directory pronte ad essere copiate sui vari client.

  3. Avatar Marcello
    Marcello

    Ciao, ottima guida!
    ho la necessità di aggiungere un utente senza modificare o cancellare gli utenti creati durante l’installazione, quindi eseguo:
    ./build-key ./keys/pippo
    per creare l’utente pippo, ma dopo aver dato questo comando mi compare il seguente errore:

    Please edit the vars script to reflect your configuration,
    then source it with “source ./vars”.
    Next, to start with a fresh PKI configuration and to delete any
    previous certificates and keys, run “./clean-all”.
    Finally, you can run this tool (pkitool) to build certificates/keys.

    ho paura di combinare qualche pasticcio ed annullare i certificati già creati per gli utenti.

    Qual’è la procedura giusta per aggiungere un utente?
    Ti ringrazio in anticipo….. ciao

  4. Avatar Francesco Pedrini

    Ciao Marcello, grazie!
    Per quanto riguarda il tuo problema, la soluzione è semplice: basta lanciare il comando “source ./vars” prima di creare la chiave, l’importante è non lanciare il comando “./clean-all”, che distruggerebbe tutto il database delle chiavi.
    Se preferisci, puoi rimuovere direttamente quello script con un colpo di rm, in caso di necessità fai sempre in tempo a copiarlo dalla directory degli esempi di openvpn citata nell’articolo.

  5. Avatar jjen
    jjen

    non ho ancora finito di seguire la tua guida, tuttavia volevo iniziare a segnalare che a me il diffy ./build-dh mi genera una chiave 1024, che quindi fa segnalata nel richiamo dei certificati al file di configurazione 😉
    Ciauz

  6. Avatar Eugenio
    Eugenio

    Salve, ho letto la tua guida per OpenVPN e devo dire che se l’avessi letta qualche annetto fa forse le cose mi sarebbero risultate più facili.
    Se posso vorrei porti un piccolo problema che mi sta assillando in questi ultimi giorni.
    Nel mio lavoro ho la necessità di connettere parecchi client VPN ad un server e ogniuno di questi DEVE avere un suo indirizzo IP statico specifico. Fino adesso ho usato gli IP 10.23.24.xx solo che sono arrivato al limite e vorrei che i prossimi assumessero l’IP 10.24.25.xx. Purtroppo però non riesco a trovare la configurazione giusta del server.conf. Puoi aiutarmi?
    Grazie mille in anticipo.
    Eugenio.

  7. Avatar Francesco Pedrini

    Ciao Eugenio,

    Non sono sicuro che la soluzione sia semplice… Oltretutto non mi e’ mai capitato quindi non ho idea se cio’ che sto per proporre sia funzionante.

    Sicuramente la strada piu’ facile e’ tirare su una seconda istanza di OpenVPN usando un nuovo tun device (tun1 ad esempio) e che usi il nuovo range di ip.

    In alternativa potresti tentare di usare una subnet piu’ grande per i tuoi client.

    Terza alternativa che mi viene in mente e’ usare una client-config-dir in cui impostare singolarmente i vari indirizzi per i client, pero’ e’ una soluzione decisamente poco scalabile.

    Alternativa 4 che in realta’ e’ una variante della terza, potresti crearti un piccolo script da usare come connect script e che assegni un ip ad ogni client sulla subnet che preferisci.

    Come ho detto poco sopra, non mi sono mai trovato nella situazione e non ho idea di quale possa essere l’approccio migliore (e onestamente non sono sicuro nemmeno di cosa ‘migliore’ possa voler dire in questo caso), direi che l’unica e’ sperimentare!

    Francesco

  8. Avatar riccardo
    riccardo

    Ciao Francesco,
    Innanzi tutto grazie per la guida molto chiara, ho solo un po di problemi per la configurazione del client e su come vedere sulla rete locale il server remoto.
    Grazie mille in anticipo,
    Riccardo

  9. Avatar Simone
    Simone

    Ciao,
    intanto anch’io mi unisco ai ringraziamenti per la guida.
    sono un po’ alle prime armi con linux ma l’ho letta e credo di essere in grado di seguirla, però prima avrei una domandina… il mio scopo è usare un client windows per connettermi al mio server linux con openvpn. Non mi interessa tanto la rete locale, ma usare la connessione del server linux per accedere a internet, visto che da dove sono, è quasi tutto bloccato, e la soluzione per me è passare per il mio server.
    le due domande che vorrei farti sono:
    1. non ho visto creazioni di utenti nella guida, il sistema non chiede quindi nome e password? io le vorrei altrimenti entrano tutti! come faccio?
    2. la configurazione attuale permette anche di accedere alla rete esterna quindi internet oppure solo alla lan?
    grazie se avrai la voglia e la pazienza di rispondermi

  10. Avatar Giulio

    Ciao, complimenti per la guida, è la prima che seguo a non darmi errori!
    L’unico problema è che dopo essermi collegato (da Android con l’applicazione openvpn) non va internet. Ho Debian e il router fastweb con gli indirizzi privati che vanno da 192.168.1.128 in poi.
    Grazie.

  11. Avatar Stragnagn
    Stragnagn

    Rispondo io SOLO 4 anni dopo.
    Guarda che non è che “entrano tutti”… Entra solo chi ha le chiavi giuste del client ed il certificato del server.
    Tutti gli altri utenti della tua macchina e tutti gli altri curiosoni in genere rimangono bellamente fuori.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *