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

11

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!