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.
apt install wireguard-tools
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pubumask 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.
[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[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
AllowedIPsstabilisce che cosa entra nel tunnel: qui l'indirizzo del server e la rete del laboratorio (split tunnel). Con0.0.0.0/0passerebbe tutto il traffico ewg-quickimposterebbe anche la route predefinita. PersistentKeepalive = 25invia 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.
chmod 600 /etc/wireguard/wg0.conf
wg-quick up wg0Per 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.
wg-quick down wg0
systemctl enable --now wg-quick@wg0Perché il server inoltri i pacchetti tra tunnel e rete locale serve l'inoltro IPv4.
net.ipv4.ip_forward = 1sysctl --systemI 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.
wg showinterface: 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 agoSe 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.
[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[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 = 25La 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;
AllowedIPsdi 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, campoPresharedKey) aggiunge un ulteriore livello simmetrico. - Privilegio minimo. I client VPN raggiungono solo le destinazioni necessarie, con regole sull'interfaccia
wg0e, 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 showe il valore dilatest handshakeindicano se un peer è attivo. I file di configurazione hanno permessi600e le loro copie vanno cifrate, perché contengono la chiave privata.