OpenVPN “bridged” su Ubuntu 14.04
Essendo passato diverso tempo aggiorno l’articolo scritto OpenVPN “bridged” su Ubuntu Lucid Lynx per la versione nuova di Ubuntu 14.04 Trusty Tahr.
Nota: avendo notato in passato che in alcune circostanze se la macchina oltre a fare da server VPN si occupa anche da fare da gateway falliscono le operazioni di re-indirizzamento verso l’interno ( nel caso ci fossero e servissero ), in questi casi occorre disabilitare il bridge-nf-call-iptables:
1 |
sudo echo "0" > /proc/sys/net/bridge/bridge-nf-call-iptables |
Sempre più spesso abbiamo necessità che portano a collaboratori esterni il dover accedere a risorse interne alla nostra LAN.
Per molti casi è più veloce mettere mano al router e aprire le porte che instradino il traffico verso le risorse ( esempio una connessione RDP o VNC verso una macchina ) ma sotto aspetti più complessi non è una soluzione accettabile, ad esempio se serve accedere a molte macchine interne che offrono gli stessi servizi e che richiedono quindi la mappatura sul router molte di porte diverse oppure se vogliamo che le nostre informazioni viaggino in maniera sicura in forma cifrata.
In questo caso è necessario appoggiarsi a soluzioni VPN.
Ci sono in giro molte soluzioni VPN diciamo facili dette server-less ovvero che si appoggiano a server esterni per le operazioni di autenticazione e instradamento, soluzioni ad esempio come LogMeIn Hamachi, Comodo EasyVPN o Wippien, ma spesso queste soluzioni richiedono un canone annuale, non sono multi-piattaforma o semplicemente non ci garba che i nostri dati passino a casa degli altri.
Una soluzione gratuita e multi-piattaforma è OpenVPN, il sistema è molto potente e versatile e di conseguenza è anche complesso per certi versi.
Installazione server
Innanzitutto installiamo la parte server sulla nostra macchina con Ubuntu 14.04:
1 |
sudo apt-get install openvpn easy-rsa |
Creiamo ora i certificati, per evitare che ad ogni aggiornamento perdiamo i dati facciamo anche una copia dei file di configurazione in un percorso diverso da quello di default:
1 2 |
sudo mkdir /etc/openvpn/easy-rsa/ sudo cp /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/ |
Ora modifichiamo i parametri di default che verranno utilizzati nelle chiavi con i nostri o quelli che riguardano la situazione, quindi apriamo il file vars:
1 |
sudo nano /etc/openvpn/easy-rsa/vars |
E modifichiamo i seguenti valori:
1 2 3 4 5 6 |
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" |
Creazione certificati server
Ora procediamo alla generazione dei certificati del nostro server VPN ( il comando build-dh è facile che impieghi molto tempo a seconda delle prestazioni della macchina ):
1 2 3 4 5 6 7 8 9 |
cd /etc/openvpn/easy-rsa/ source vars ./clean-all ./build-dh ./pkitool --initca ./pkitool --server server cd keys openvpn --genkey --secret ta.key sudo cp server.crt server.key ca.crt dh2048.pem ta.key /etc/openvpn/ |
- la generazione della chiave ta.key serve per i client quando effettuano la prima connessione al server in modo da avere il permesso per procedere con le fasi di autenticazione, è una protezione che gli evita attacchi di tipo Denial of Service e lascia passare alla fase successiva solo chi è effettivamente abilitato;
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/easy-rsa/ source vars ./build-key hostname |
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 hostname |
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/ca.crt
- /etc/openvpn/easy-rsa/keys/hostname.crt
- /etc/openvpn/easy-rsa/keys/hostname.key
- /etc/openvpn/ta.key
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.
Configurazione server
Procediamo ora alla configurazione del nostro server, creiamo il file server.conf partendo dall’esempio fornito dal pacchetto:
1 2 3 |
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/ sudo gzip -d /etc/openvpn/server.conf.gz sudo nano /etc/openvpn/server.conf |
In questo caso procederemo alla configurazione detta bridged, 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.
Nel caso la macchina facesse anche da gateway e quindi abbia due schede di rete ( eth0 la LAN e eth1 la WAN ), quella da usare per le operazioni di bridge è quella associata alla LAN interna ( di solito eth0 ).
Prima di tutto nel caso non avessimo il pacchetto bridge-utils andiamo a installarlo:
1 |
sudo apt-get install bridge-utils |
Dal sito ufficiale di OpenVPN è disponibile uno script che si occupa di creare il bridge, si chiama bridge-start ( per comodità riporto lo script intero ):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#!/bin/bash ################################# # Set up Ethernet bridge on Linux # Requires: bridge-utils ################################# # Define Bridge Interface br="br0" # Define list of TAP interfaces to be bridged, # for example tap="tap0 tap1 tap2". tap="tap0" # Define physical ethernet interface to be bridged # with TAP interface(s) above. eth="eth0" eth_ip="192.168.8.4" eth_netmask="255.255.255.0" eth_broadcast="192.168.8.255" for t in $tap; do openvpn --mktun --dev $t done brctl addbr $br brctl addif $br $eth for t in $tap; do brctl addif $br $t done for t in $tap; do ifconfig $t 0.0.0.0 promisc up done ifconfig $eth 0.0.0.0 promisc up ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast |
I parametri che vanno modificati sostanzialmente sono:
- eth: nome dell’interfaccia fisica di rete da utilizzare per il bridge;
- eth_ip: indirizzo ip utilizzato dal bridge, va bene lo stesso ip attualmente assegnato alla scheda di rete;
- eth_netmask: la maschera di rete;
- eth_broadcast: l’indirizzo di broadcast della rete;
Aggiunta: Può capitare in certe situazioni che dopo aver tirato su il bridge di rete la macchina anche se vista dalla rete interna risulta irraggiungibile dall’esterno, dopo varie prove ho notato che in quel caso viene a mancare il parametro del gateway, quindi è sufficiente aggiungerlo in seguito:
1 |
sudo route add default gw 192.168.8.1 |
Oppure se vogliamo modificare lo script sopra, aggiungiamo il parametro configurabile all’inizio ( subito sotto eth_broadcast ):
1 |
eth_gateway="192.168.8.1" |
E poi aggiungiamo il comando route alla fine dello script:
1 |
route add default gw $eth_gateway |
Sul sito esiste anche lo script eventualmente da usare per rimuovere il nostro bridge, si chiama bridge-stop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#!/bin/bash #################################### # Tear Down Ethernet bridge on Linux #################################### # Define Bridge Interface br="br0" # Define list of TAP interfaces to be bridged together tap="tap0" ifconfig $br down brctl delbr $br for t in $tap; do openvpn --rmtun --dev $t done |
Per avviare il tutto occorrerà eseguire in successione prima lo script bridge-start e dopo avviare il demone openvpn:
1 2 |
sudo bridge-start sudo /etc/init.d/openvpn start |
E di conseguenza se volessimo fermarlo dovremo prima fermare il demone e in seguito eseguire bridge-stop:
1 2 |
sudo /etc/init.d/openvpn stop sudo bridge-stop |
Comunque prima di avviare il demone andiamo a modificare il file /etc/openvpn/server.conf ( sotto la spiegazione dettagliata ):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
port 1194 proto udp dev tap0 ca /etc/openvpn/ca.crt cert /etc/openvpn/server.crt key /etc/openvpn/server.key dh /etc/openvpn/dh1024.pem tls-auth /etc/openvpn/ta.key 0 ;server 10.8.0.0 255.255.255.0 server-bridge 192.168.8.4 255.255.255.0 192.168.8.128 192.168.8.254 push "route 192.168.8.0 255.255.255.0" push "dhcp-option DNS 192.168.8.8" push "dhcp-option WINS 192.168.8.8" push "dhcp-option DOMAIN mydomain.loc" max-clients 10 ifconfig-pool-persist /etc/openvpn/ipp.txt 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;
- 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, si basa sull’hostname;
- 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 proviamo prima di tutto a far partire a mano il server per vederne i log a video nel caso qualcosa non vada come dovrebbe ( ricordandoci ovviamente di far partire il bridge prima se ancora non l’abbiamo fatto ):
1 2 |
sudo bridge-start sudo openvpn --config /etc/openvpn/server.conf --verb 4 |
Il parametro –verb indica il livello di log, maggiore lo mettiamo più dettagliato avremo il log, può arrivare fino a 9.
Di default OpenVPN si installa come avvio automatico ai runlevel 2-3-4-5, quindi dobbiamo ricordarci di toglierlo perchè prima dobbiamo far partire il bridge.
1 |
sudo update-rc.d openvpn disable |
E’ necessario inoltre che sul nostro server che fa da bridge sia abilitato 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 |
sudo 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.
Configurazione client Ubuntu
Installiamo ovviamente il pacchetto openvpn:
1 |
sudo 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 |
sudo 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 tap 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 ) non avvengono in automatico ma 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 ).
Anche in questo caso la prima volta magari invece che seguire il demone possiamo farlo partire a mano per vederne i log a video:
1 |
sudo openvpn --config /etc/openvpn/client.conf --verb 4 |
Altrimenti basta un:
1 |
sudo /etc/init.d/openvpn start |
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
Noto con piacere che il pacchetto openvpn-gui rispetto alle versioni vecchie di OpenVPN è stato incluso nel pacchetto base e non serve installarlo a parte, il file di configurazione va comunque fatto a mano.
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 |
dev tap proto udp remote [ip o host del server] 1194 ca ca.crt cert hostname.crt key hostname.key tls-auth ta.key 1 |
A questo punto possiamo salvare e chiudere.
Nel menu Programmi di Windows, nel gruppo OpenVPN abbiamo il programma OpenVPN GUI, lanciamolo e avremo un icona con due terminali rossi vicino nella barra vicino all’orologio.
Avendo una configurazione sola possiamo anche fare doppio click sull’icona e automaticamente partirà la connessione, e se tutto va come deve saremo collegati in VPN con il server e lo vedremo dall’icona che da terminali rossi, diventano prima gialli durante il tentativo e poi verdi a connessione effettuata.
Il client Windows a differenza di quello di Ubuntu di prima ho riscontrato che tutti i vari push impostati dal server funzionano perfettamente, quindi ad esempio possiamo richiamare un host remoto anche tramite il suo nome registrato nel server DNS dietro VPN.
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/easy-rsa/ sudo source vars sudo ./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 |
sudo cp keys/crl.pem /etc/openvpn/ |
Controllate nella configurazione del server che esista la riga ( altrimenti aggiungetela ):
1 |
crl-verify /etc/openvpn/crl.pem |
Ora basta dire al server di aggiornarsi i parametri in maniera che al client revocato non venga dato più accesso alla VPN:
1 |
sudo /etc/init.d/openvpn reload |