VPN del GOLEM
In questa pagina sono descritti i dettagli implementativi della VPN del GOLEM.
Molte configurazioni descritte in questa pagina sono state fatte nell'ottica (anche) di fornire IPv6, per cui si consiglia la lettura della pagina dedicata. Eventualmente (un giorno) le due pagine verranno (forse) accorpate.
Cos'è una VPN
VPN è un acronimo che sta per Virtual Private Network, cioè rete virtuale privata. I computer che comunicano attraverso una VPN agiscono come se fossero tutti collegati fisicamente alla stessa LAN (Local Area Network).
Vantaggi:
- i computer possono essere dislocati fisicamente in posti molto distanti
- possono utilizzare infrastrutture di rete con tecnologie molto diverse (Ethernet, WiFi, 4G, WiiMax, ...)
- possono stare dietro un NAT (tradotto, non c'è bisogno di "aprire porte" sul router)
- sembra di lavorare con macchine locali
- i dati che passano attraverso la VPN sono cifrati
Ci sono anche delle limitazioni ovvie:
- bassa velocità
- elevata latenza
Possiamo considerare due tipi di VPN:
- VPN brigded: si fa un bridge unendo le due reti in cui si trovano i computer, come se si prendesse un cavo (parecchio lungo) e si attaccassero i client ad uno stesso switch;
- VPN routed: i dati in transito tra un client e l'altro sono smistati ad un livello più alto (pacchetto IP)
Nelle VPN routed ci sono alcune limitazioni apparentemente meno ovvie, tra cui:
- non funziona il broadcast (no DHCP, no stampanti di rete, DLNA, SMB automatici)
Anche senza broadcast, si possono fare tante cose, e alcune applicazioni che ne fanno uso potrebbero comunque funzionare, a patto di ricorrere a configurazioni manuali sui client.
A noi bastano le VPN routed, quindi non ci soffermeremo su questi aspetti.
A cosa ci serve
Nella nostra Officina Informatica abbiamo vari computer, tra cui sicuramente:
- un server per smistamento del traffico e cache dei pacchetti
- il computer di sala corsi
- il computer di officina
Maggiori dettagli sulla Rete del GOLEM possono essere trovati sulla pagina dedicata.
Perché ci serve una VPN:
- A volte bisogna effettuare manutenzione su queste macchine, ma non lo si può fare in loco a causa della mancanza di tempo (in genere quando si è in officina - cioè una volta alla settimana - è necessario dedicarsi alle attività principali).
- La nostra rete sta dietro un NAT: tradotto: non possiamo aprire porte per accedere alle macchine.
- I dati che scambiamo con le macchine in officina, quelle a casa, e il VPS, devono essere cifrati.
- Ci piace spippolare e fare serate a tema spippolamento :-)
Quindi, ci serve una VPN.
Requisiti
- un server (useremo il nostro VPS)
- un software VPN (useremo OpenVPN, è in sperimentazione wireguard)
- client per la rete (ma va?)
Wireguard
Sul server, installiamo wireguard e wireguard-tools. Il primo pacchetto contiene il core della gestione VPN, il secondo ci è utile per amministrare facilmente le connessioni (vedi wg-quick).
apt install wireguard wireguard-tools
Su sistemi debian <= 10 (buster), il pacchetto non è presente nei repository mainline ma deve essere aggiunto tramite i debian backports.
Configurazione del server
A differenza di altri protocolli VPN come OpenVPN, wireguard ha un approccio "peer to peer", per cui la procedura di configurazione del server rispecchia per buona parte quella di ciascun client.
Innanzitutto è necessario generare la coppia di chiavi pubblica/privata del server
# wg genkey | tee /etc/wireguard/server.privkey | wg pubkey > /etc/wireguard/vpn.golem.linux.it.pubkey
Per la configurazione è sufficiente creare un singolo file, ad esempio /etc/wireguard/wg0.conf
[Interface] # Carica la chiave privata dal percorso dove la abbiamo generata precedentemente PostUp = wg set %i private-key /etc/wireguard/vpn.golem.linux.it.privkey # Porta UDP di ascolto del server, a piacere ListenPort = 51820 # Indirizzo del server all'interno della VPN Address = 10.40.0.1
Il server può essere avviato tramite systemd, e con lo stesso sistema si può impostare l'avvio automatico.
Si noti che @wg0
corrisponde al file di configurazione precedentemente creato.
# systemctl start wg-quick@wg0 # systemctl enable wg-quick@wg0
Configurazione del client
In maniera duale, è necessario creare una coppia di chiavi pubblica/privata appartenenti al client.
$ wg genkey | tee client.example.com.privkey | wg pubkey > client.example.com.pubkey
La chiave privata deve essere distribuita all'utente, assieme al file di configurazione. Si noti che alla riga PublicKey deve essere inserita la chiave pubblica del server.
[Interface] # Caricamento della chiave privata dal file generato in precedenza PostUp = wg set %i private-key ./client.example.com.privkey # Indirizzo del client nella VPN Address = 10.40.0.2 [Peer] # Chiave pubblica del server PublicKey = ... # Indirizzi raggiungibili tramite la VPN. In questo caso, solo la sottorete della VPN AllowedIPs = 10.40.0.0/24 # Indirizzo del server VPN Endpoint = vpn.example.com:51820 # Timer, in secondi, di mantenimento del tunnel attivo. Utile se il client è nattato PersistentKeepalive = 30
Lato server, il client dovrà essere abilitato alla connessione.
È sufficiente aggiungere un blocco peer per ciascun client alla configurazione /etc/wireguard/wg0.conf
[Peer] # client.example.com # Chiave pubblica del client PublicKey = ... # Indirizzi sorgente delle connessioni provenienti dal client AllowedIPs = 10.40.0.2
La connessione può essere attivata tramite systemd come sul server (la configurazione deve essere spostata in /etc/wireguard/), oppure manualmente utilizzando wg-quick
# Attivazione del tunnel wg-quick up client.example.conf # Disattivazione del tunnel wg-quick down client.example.conf
OpenVPN
Sul server, installiamo openvpn e anche easy-rsa (che ci servirà per generare le chiavi). Su Debian:
apt-get install openvpn easy-rsa
Configurazione server
Sul server deve essere creata una propria CA (Certificate Authority), che deve firmare tutti i certificati che andremo a utilizzare nella VPN. Per fare questo useremo la collezione di utili script easy-rsa. Per semplificarci il lavoro, lavoreremo nella directory /etc/openvpn, e ci copieremo anche gli script easy-rsa.
cp /usr/share/easy-rsa/* /etc/openvpn
Digressione inutile: io avrei messo /usr/share/easy-rsa/ nel PATH, ma quelli di OpenVPN dicono di copiare gli script per evitare problemi di compatibilità (es. oggi creo la mia fantastica VPN con easy-rsa versione $oggi, domani aggiorno easy-rsa a versione $domani, e dopodomani voglio aggiungere un nuovo client alla mia VPN ma non posso farlo perché agli script nuovi non piace la vecchia CA). Insomma, agli script non piacciono i certificati, a me non piace questo modo di fare, a tutti non piace qualcosa, poggio e buca fa pari, animo in pace, quindi facciamolo e basta.
Variabili d'ambiente
Modifichiamo le righe dello script vars. I valori inseriti qui saranno utilizzati di default per la generazione dei certificati, quindi, quando li genereremo, ci basterà premere Invio per far prima.
# These are the default values for fields # which will be placed in the certificate. export KEY_COUNTRY="IT" export KEY_PROVINCE="FI" export KEY_CITY="Empoli" export KEY_ORG="GOLEM - Gruppo Operativo Linux Empoli" export KEY_EMAIL="golem@mailinator.com" export KEY_OU="VPN Task Force" ... export KEY_SIZE=2048
Popoliamo l'ambiente eseguendo lo script:
# . ./vars
Creazione CA
# ./clean-all # ./build-ca
ATTENZIONE: questi comandi distruggono l'eventuale CA che già abbiamo creato, quindi usiamoli solo la prima volta, a meno che non siamo masochisti e vogliamo ripartire da zero, buttar via tutto e impedire ai client (che già abbiamo) di collegarsi alla VPN. Una catastrofe insomma.
Nota: clean-all crea anche una nuova directory keys, dove sono salvate tutte le chiavi che abbiamo generato, e che genereremo da ora in avanti. Ci servirà più avanti.
Generazione parametri Diffie-Hellman
# ./build-dh
Ci vorrà un po', in base alla KEY_SIZE che abbiamo specificato in vars. Questo genererà un file dh2048.pem (o 1024, dipende dalla dimensione) nella directory keys. Ci servirà più avanti.
Generazione chiave server
# ./build-key-server golem.linux.it
dove golem.linux.it è l'hostname del nostro server. Non è necessario usare l'hostname vero, ma ci aiuta a tenere le cose ordinate. Possiamo avere tutte le chiavi che vogliamo, ma ce ne basta una (eventualmente anche per più VPN). Ci servirà più avanti.
File di configurazione server.conf
Copiamo il modello fornito da OpenVPN:
# zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
Modifichiamolo:
port 7777 # porta su cui è in ascolto OpenVPN proto udp # usare il protocollo UDP dev tun # VPN routed ca /etc/openvpn/keys/ca.crt # certificato CA cert /etc/openvpn/keys/server.crt # chiave pubblica server key /etc/openvpn/keys/server.key # chiave privata server dh /etc/openvpn/keys/dh2048.pem # parametri Diffie-Hellman server 10.60.73.0 255.255.255.0 # indirizzi IP della rete ;ifconfig-pool-persist ipp.txt # ricorda gli indirizzi IP assegnati ai client? client-config-dir /etc/openvpn/staticclients # directory configurazioni specifiche dei client client-to-client # permetti ai client di parlarsi tra loro user nobody # rilascia i privilegi una volta finito group nogroup topology subnet # tutti i client nella sottorete (no point-to-point) comp-lzo # attiva la compressione lzo
Osservazioni:
- proto: utilizziamo il protocollo UDP, perché TCP su TCP può portare al collasso della rete
- nella rete 10.60.73.0/24, il server prende automaticamente il primo indirizzo disponibile, cioè 10.60.73.1
- ifconfig-pool-persist: abilitato di default, memorizza nel file ipp.txt le associazioni client/indirizzo. Se dobbiamo poter raggiungere le macchine nella rete, queste dovranno avere un IP fisso, quindi in teoria questa cosa ci piace, ma in pratica no perché vogliamo mettere gli indirizzi a mano secondo una logica sensata, quindi commentiamo questa riga.
- client-config-dir: in questa directory andremo a inserire le configurazioni specifiche dei client (es. l'IP statico)
- client-to-client: lo mettiamo perché vogliamo che i client possano dialogare tra loro direttamente, senza dover ammattire col firewall
- user e group: OpenVPN gira come root, e quando ha instaurato le connessioni e ha finito di fare il suo lavoro, è bene che rilasci i privilegi e continui a girare come utente semplice.
- topology: indica il tipo di rete. Facciamo attenzione a aggiungerlo manualmente, perché altrimenti, per ragioni di retrocompatibilità, viene utilizzata la modalità point-to-point
Avvio del server
Proviamo:
# openvpn server.conf
Per avviare il servizio o abilitarlo permanentemente:
# systemctl [start|stop|restart|reload|enable] openvpn@server.conf
dove server.conf viene cercato nella directory /etc/openvpn.
Vediamo che adesso abbiamo una nuova interfaccia di rete virtuale denominata tun0 con indirizzo IP 10.60.73.1. Questa è la scheda che è attaccata al nostro lungo "filo" immaginario.
# ip addr
Aggiungere un client
Generazione chiave client
Sempre sul server:
# ./build-key client-numero-uno
Oss: utilizziamo un nome significativo. Come prima, consiglio di usare l'hostname.
Oss: probabilmente vogliamo utilizzare lo stesso ambiente vars di prima.
Oss: verrà generata la coppia di chiavi pubblica/privata client-numero-uno.cert/client-numero-uno.key nella directory keys.
Copiamo le chiavi client-numero-uno.* e anche ca.crt sul client (es. scp) e mettiamole in /etc/openvpn/golem.linux.it/.
Installazione OpenVPN
Sul client:
# apt-get install openvpn # Debian # pacman -S openvpn # Arch
File di configurazione client.conf
Copiamo il modello del file di configurazione del client in un posto sensato, tipo in /etc/openvpn/ o /etc/openvpn/client/.
Es su Arch Linux:
# cp /usr/share/openvpn/examples/client.conf /etc/openvpn/client/
Percorso su Debian:
/usr/share/doc/openvpn/examples/sample-config-files/client.conf
Modifichiamolo. Per brevità ometto cose tipo proto udp, tun e via discorrendo, che devono ovviamente corrispondere anche lato server.
remote golem.linux.it 7777 user nobody group nobody ca /etc/openvpn/golem.linux.it/ca.crt cert /etc/openvpn/golem.linux.it/client-numero-uno.crt key /etc/openvpn/golem.linux.it/client-numero-uno.key keepalive 30 120 # riattiva le connessioni chiuse comp-lzo
# Nel template Debian si commenta la configurazione di questo certificato (opzionale). ;tls-auth ta.key 1
Osservazioni:
- remote: hostname e porta del server OpenVPN
- keepalive X Y: ogni X secondi, controlla la connessione con il server, e se questa risulta assente per più di Y secondi consecutivi, si riconnette
- group: su Debian deve essere specificato
nogroup
anzichénobody
Attenzione alle eventuali modalità di compressione e/o di cifratura (qui è attiva la compressione lzo), che devono corrispondere a quelle sul server. È facile che si abbiano impostazioni leggermente diverse a seconda del sistema che si usa (Debian, Arch, ...)
Assegnare IP fisso al client
Torniamo sul server e nella directory /etc/openvpn/staticclients (scelta prima nel server.conf) aggiungiamo un file per ogni client a cui si vuole assegnare un indirizzo statico. Il file deve chiamarsi come l'hostname del client (l'hostname che avete dichiarato nel certificato! Se è diverso dall'hostname vero, siete masochisti, e poi non dite che non avevo avvertito). All'interno inserire una direttiva ifconfig-push.
Esempio, file /etc/openvpn/staticclients/client-numero-uno:
ifconfig-push 10.60.73.77 255.255.255.0
dove 10.60.73.184.77 è l'IP che vogliamo assegnare al client che si presenta col certificato di client-numero-uno e 255.255.255.0 è la sua maschera di rete.
Avvio del client
Proviamo (uguale al server):
# openvpn client.conf
Per avviare il servizio o abilitarlo permanentemente:
- su Debian
# systemctl [start|stop|restart|reload|enable] openvpn@client.conf
dove client.conf viene cercato nella directory /etc/openvpn
- su Arch
# systemctl [start|stop|restart|reload|enable] openvpn-client@client.conf
dove client.conf viene cercato nella directory /etc/openvpn/client
Revoca di un certificato
Per revocare l'accesso a un client, è sufficiente revocare la sua chiave attraverso il comando:
# ./revoke-full client-numero-1
Nota bene: questo comando termina con Errore 23; secondo la documentazione ufficiale di OpenVPN, è tutto normale, in quanto, dopo aver revocato il certificato, lo script ricontrolla la sua firma, che a questo punto risulta non più valida.
Un altro modo per vedere se il certificato è stato revocato consiste nel listare il contenuto del file keys/index.txt e controllare che appaia una R (e un nuovo timestamp) accanto al certificato che si intendeva revocare.
Verifiche finali
Controlliamo di avere una nuova interfaccia di rete virtuale tun0 con l'indirizzo IP desiderato:
# ip addr
Proviamo il ping:
# ping 10.60.73.1
Accesso dall'esterno
Può essere interessante accedere ai servizi offerti da uno degli host interni alla VPN, ma senza accedere alla VPN. Ad esempio collegarsi ad un sistema di monitoraggio webcam remoto utilizzando la rete 3G del cellulare.
Per fare questo si può sfruttare l'IP pubblico del server VPN: impartendo alcune istruzioni iptables si va a monitorare una determinata porta (ad esempio 1234) e si indirizzano le richieste verso l'host interno alla VPN (che, per esempio, ha IP 10.60.73.12)
iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 10.60.73.12:1234 iptables -t nat -A POSTROUTING -j MASQUERADE sysctl net.ipv4.ip_forward=1
L'opzione dport
può essere variata a piacere se si vuole reindirizzare richieste da una porta verso un'altra:
iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 10.60.73.12:12
In questo modo si varia anche la porta. Può essere utile per evitare conflitti con server già presenti sulla macchina che si va ad interrogare.
Connessione tramite grafica
Per effettuare una connessione VPN tramite il gestore di rete grafico, è necessario installare il pacchetto networkmanager-openvpn
. La configurazione varia leggermente a seconda del Desktop Environment utilizzato.
KDE
- Aprire le impostazioni di rete tramite l'icona nella barra di stato o direttamente dalle impostazioni di sistema
- Cliccare su "Aggiungi una nuova connessione"
- Selezionare openvpn (figura 1)
- Inserire i 3 certificati nella scheda VPN come specificato nella sezione #File di configurazione client.conf (figura 2)
- Modificare la porta nel sottomenu Avanzate... (figura 3)
- Nella scheda IPv4 selezionare Automatico (solo indirizzi) (figura 4)
- Spuntare le due caselle nel sottomenu Rotte... (figura 5)
Gnome
...ToDo...