m4nifest0-tech

Cerca nel sito

Networking

WireGuard: accesso remoto e VPN site-to-site senza complicazioni

Guida a WireGuard su Debian: chiavi, configurazione di server e client, inoltro IP, VPN site-to-site tra due sedi e buone pratiche di gestione dei peer.
Pubblicato il 7 min di letturaLivello: Intermedio

WireGuard è una VPN integrata nel kernel Linux con una configurazione ridotta a pochi file di testo: ogni dispositivo ha una coppia di chiavi, elenca i peer con cui comunica e dichiara quali indirizzi può raggiungere attraverso ciascuno. Il protocollo non distingue tra server e client: il «server» è semplicemente il peer con un indirizzo raggiungibile. I due scenari più comuni sono l'accesso remoto di un dispositivo alla rete del laboratorio e il collegamento permanente tra due sedi; entrambi sono descritti qui per Debian 12 e 13.

Come ragiona WireGuard

Il concetto centrale è AllowedIPs, che per ogni peer svolge due funzioni insieme. In uscita è una tabella di routing: un pacchetto destinato a un indirizzo compreso nell'elenco viene cifrato e inviato a quel peer. In ingresso è un filtro: un pacchetto decifrato il cui indirizzo sorgente non appartiene all'elenco del peer che l'ha inviato viene scartato. L'elenco va quindi compilato con precisione, non come un semplice insieme di reti da raggiungere. Inoltre WireGuard non risponde ai pacchetti che non provengono da un peer autenticato: verso Internet basta esporre una sola porta UDP, che non rivela alcun servizio.

Installazione e chiavi

Il supporto a WireGuard è nel kernel di Debian 12 e 13, quindi basta il pacchetto degli strumenti. Ogni dispositivo genera la propria coppia di chiavi sul dispositivo stesso: la chiave privata non deve mai lasciarlo.

Sul server (stessa procedura su ogni dispositivo)
apt install wireguard-tools
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub

umask 077 rende i file leggibili solo dal proprietario. Il contenuto di server.key va nel campo PrivateKey della configurazione; server.pub è l'unica chiave da comunicare agli altri peer. Negli esempi seguenti i valori tra parentesi angolari sono segnaposto.

Importante

Una chiave privata non si incolla mai in chat, ticket, repository o documentazione, e non si condivide tra dispositivi: la compromissione di una chiave condivisa obbliga a sostituirla ovunque.

Accesso remoto

Nell'esempio la rete del laboratorio è 192.0.2.0/24, il tunnel usa 203.0.113.0/24 e il portatile ha l'indirizzo 203.0.113.2. Il server è raggiungibile come vpn.example.com.

/etc/wireguard/wg0.conf sul server
[Interface]
Address = 203.0.113.1/24
ListenPort = 51820
PrivateKey = <CHIAVE_PRIVATA_SERVER>
 
# portatile-esempio
[Peer]
PublicKey = <CHIAVE_PUBBLICA_PORTATILE>
AllowedIPs = 203.0.113.2/32
/etc/wireguard/wg0.conf sul portatile
[Interface]
Address = 203.0.113.2/32
PrivateKey = <CHIAVE_PRIVATA_PORTATILE>
 
[Peer]
PublicKey = <CHIAVE_PUBBLICA_SERVER>
Endpoint = vpn.example.com:51820
AllowedIPs = 203.0.113.1/32, 192.0.2.0/24
PersistentKeepalive = 25
  • Sul server AllowedIPs = 203.0.113.2/32 è l'unico indirizzo sorgente accettato da quel peer: un dispositivo compromesso non può spacciarsi per un altro.
  • Sul client AllowedIPs stabilisce che cosa entra nel tunnel: qui l'indirizzo del server e la rete del laboratorio (split tunnel). Con 0.0.0.0/0 passerebbe tutto il traffico e wg-quick imposterebbe anche la route predefinita.
  • PersistentKeepalive = 25 invia un pacchetto ogni 25 secondi per mantenere aperta la mappatura NAT. Serve al peer che sta dietro un NAT e deve poter ricevere traffico; per impostazione predefinita è disattivato.
  • La porta UDP 51820 è solo una convenzione: si sceglie con ListenPort.

Nota

Il nome in Endpoint viene risolto quando l'interfaccia è configurata, non a ogni pacchetto. Se l'indirizzo pubblico del server cambia (IP dinamico), il client deve riavviare il tunnel o disporre di un meccanismo di nuova risoluzione.

Avvio, inoltro e verifica

Per una prova manuale si usa wg-quick up wg0; il file di configurazione deve essere leggibile solo da root, altrimenti wg-quick lo segnala.

Sul server: prova manuale
chmod 600 /etc/wireguard/wg0.conf
wg-quick up wg0

Per l'avvio automatico si ferma l'interfaccia e si abilita l'unità systemd, che esegue lo stesso wg-quick up a ogni avvio. I due metodi non vanno combinati sulla stessa interfaccia.

Sul server: avvio automatico
wg-quick down wg0
systemctl enable --now wg-quick@wg0

Perché il server inoltri i pacchetti tra tunnel e rete locale serve l'inoltro IPv4.

/etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward = 1
Sul server
sysctl --system

I dispositivi della rete locale devono sapere come rispondere agli indirizzi del tunnel: o il server WireGuard è il loro gateway predefinito, oppure sul router si aggiunge una route statica verso 203.0.113.0/24. In alternativa il server può mascherare (NAT) il traffico del tunnel, a costo di perdere l'indirizzo reale del client nei log. Le regole di inoltro e di NAT appartengono al firewall dell'host e vanno limitate al necessario; sul firewall perimetrale si inoltra soltanto la porta UDP scelta.

Sul server
wg show
Output di esempio (abbreviato)
interface: wg0
  public key: <CHIAVE_PUBBLICA_SERVER>
  listening port: 51820
 
peer: <CHIAVE_PUBBLICA_PORTATILE>
  endpoint: 198.51.100.77:41234
  allowed ips: 203.0.113.2/32
  latest handshake: 12 seconds ago

Se latest handshake non compare, il peer non ha mai completato lo scambio: conviene controllare le chiavi pubbliche, la raggiungibilità della porta UDP e l'Endpoint.

VPN site-to-site

Due sedi si collegano con lo stesso meccanismo, indicando come AllowedIPs le reti remote. Nell'esempio la sede A ha un indirizzo pubblico stabile e la sede B sta dietro un NAT. La rete della sede A è 192.0.2.0/24, quella della sede B 198.51.100.0/24, il tunnel 203.0.113.0/30.

Sede A: /etc/wireguard/wg0.conf
[Interface]
Address = 203.0.113.1/30
ListenPort = 51820
PrivateKey = <CHIAVE_PRIVATA_SEDE_A>
 
[Peer]
PublicKey = <CHIAVE_PUBBLICA_SEDE_B>
AllowedIPs = 203.0.113.2/32, 198.51.100.0/24
Sede B: /etc/wireguard/wg0.conf
[Interface]
Address = 203.0.113.2/30
PrivateKey = <CHIAVE_PRIVATA_SEDE_B>
 
[Peer]
PublicKey = <CHIAVE_PUBBLICA_SEDE_A>
Endpoint = sede-a.example.com:51820
AllowedIPs = 203.0.113.1/32, 192.0.2.0/24
PersistentKeepalive = 25

La sede B avvia la connessione; la sede A ne apprende l'indirizzo dai pacchetti ricevuti e per questo non ha bisogno di un Endpoint. Perché il collegamento funzioni:

  • le due reti locali hanno sottoreti diverse e non sovrapposte;
  • AllowedIPs di ciascun peer comprende la rete dell'altra sede;
  • entrambi i gateway abilitano net.ipv4.ip_forward;
  • gli host di ogni sede conoscono la route verso la rete remota (gateway predefinito oppure route statica sul router).

Attenzione

Un tunnel tra sedi non equivale a fiducia reciproca: senza filtri ogni dispositivo di una sede raggiunge tutti quelli dell'altra. Conviene consentire solo i flussi necessari. Il tunnel è, per esempio, il canale adatto per la replica dei backup verso la sede remota (si veda Strategia di backup 3-2-1 con Proxmox Backup Server).

Buone pratiche

  • Una chiave per dispositivo. Ogni dispositivo ha una coppia dedicata e un blocco [Peer] con un commento che lo identifica.
  • Revoca. Si elimina dal file il blocco del dispositivo e si applica la modifica senza interrompere gli altri tunnel con wg syncconf wg0 <(wg-quick strip wg0).
  • Rotazione. Si genera una nuova coppia sul dispositivo, si aggiorna la chiave pubblica sulla controparte e si rimuove la vecchia; conviene farlo a ogni sostituzione di dispositivo e a ogni sospetto di compromissione. Una chiave precondivisa per coppia di peer (wg genpsk, campo PresharedKey) aggiunge un ulteriore livello simmetrico.
  • Privilegio minimo. I client VPN raggiungono solo le destinazioni necessarie, con regole sull'interfaccia wg0 e, idealmente, in un segmento dedicato (si veda Segmentare la rete con le VLAN).
  • Esposizione minima. Verso Internet resta aperta solo la porta UDP; SSH e le interfacce di amministrazione si raggiungono soltanto attraverso il tunnel (si veda la checklist di hardening SSH su Debian).
  • Controllo. wg show e il valore di latest handshake indicano se un peer è attivo. I file di configurazione hanno permessi 600 e le loro copie vanno cifrate, perché contengono la chiave privata.

Articoli correlati