SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-10-01

WireGuard: instradare il traffico verso la LAN di casa

Handshake WireGuard attivo ma 192.168.20.10 non risponde? Verifica AllowedIPs, IP forwarding e route di ritorno: ecco i 4 punti da controllare.

Perché la LAN domestica non risponde tramite WireGuard

Per instradare il traffico verso la LAN domestica tramite WireGuard, devono essere coerenti quattro impostazioni separate. Anche tre impostazioni su quattro producono un tunnel che sembra perfettamente funzionante, rendendo il problema difficile da diagnosticare. wg show segnala un handshake recente, ping 10.8.0.1 risponde in pochi millisecondi e ping 192.168.20.10 non restituisce alcun risultato.

Di seguito è riportato l'elenco completo, nell'ordine in cui un pacchetto incontra queste impostazioni. LAN significa rete locale, ovvero la rete privata dietro il router domestico.

  1. AllowedIPs sul client deve includere la subnet remota, altrimenti il pacchetto non entra mai nel tunnel.
  2. AllowedIPs sul server deve includere l'indirizzo del tunnel del client, altrimenti il pacchetto viene scartato non appena viene decrittografato.
  3. net.ipv4.ip_forward deve essere 1 sul server, perché Linux scarta ogni pacchetto non indirizzato al server stesso.
  4. La LAN deve conoscere una route di ritorno verso 10.8.0.0/24, tramite una regola di masquerade sul server oppure una route statica sul router domestico.

Tutte queste impostazioni possono fallire senza generare messaggi di errore. Non viene scritto alcun log, non viene visualizzato alcun avviso e l'handshake continua a funzionare per tutto il tempo. Verificale nell'ordine indicato: l'impostazione errata viene individuata in circa un minuto.

La rete utilizzata da questa guida

Tutti gli indirizzi riportati di seguito sono esempi. Sostituiteli con i vostri e mantenete la coerenza tra i valori, perché una configurazione aggiornata solo in parte è la seconda causa più comune di questo problema.

  • La LAN domestica è 192.168.20.0/24. Il router domestico è 192.168.20.1.
  • Il server WireGuard è un sistema Linux collegato a questa LAN. La sua interfaccia LAN enp1s0 contiene 192.168.20.5, mentre l’interfaccia tunnel wg0 contiene 10.8.0.1.
  • L’host che volete raggiungere è un NAS (network attached storage) all’indirizzo 192.168.20.10.
  • Il client è un laptop situato altrove, 10.8.0.2 all’interno del tunnel.

Il server è un computer collegato alla LAN, non il router stesso. È la configurazione normale: ad esempio un Raspberry Pi o un vecchio mini PC. Questo è importante per la regola 4: il router non sa che esiste il tunnel finché non glielo indicate e ogni host della LAN invia al router il traffico destinato a reti esterne alla propria subnet.

Se la connessione domestica non dispone di un indirizzo IP pubblico, questa configurazione non funziona autonomamente, perché nessun sistema su Internet può avviare un handshake verso la vostra rete domestica. La sezione dedicata all’inserimento di un VPS come intermediario tratta questo caso. Le stesse quattro regole restano valide, con un peer aggiuntivo da considerare.

AllowedIPs indica due cose diverse

Una singola impostazione svolge due funzioni. Interpretarla allo stesso modo sui due lati è l'errore alla base della maggior parte di questi ticket. WireGuard chiama questo meccanismo cryptokey routing, descritto più dettagliatamente in come WireGuard associa le chiavi pubbliche agli intervalli IP.

In lettura in uscita, AllowedIPs è una tabella di routing. wg-quick trasforma ogni voce in una route che punta a wg0. Un pacchetto destinato a 192.168.20.10 viene cifrato e inviato a un peer solo se un peer dichiara un intervallo che contiene quell'indirizzo. Indicate soltanto 10.8.0.0/24 e il laptop invia invece il traffico LAN tramite la rete Wi-Fi locale, dove il traffico viene scartato oppure raggiunge un 192.168.20.10 completamente diverso.

In lettura in ingresso, AllowedIPs è una lista di controllo degli accessi. Dopo aver decifrato un pacchetto proveniente da un peer, WireGuard confronta l'indirizzo sorgente interno con AllowedIPs di quel peer e scarta il pacchetto se non corrisponde. Per questo scarto non viene registrata alcuna riga di log e non viene incrementato alcun contatore. Il pacchetto scompare semplicemente.

I due file di configurazione, quindi, non sono mai immagini speculari. Il client elenca le destinazioni che vuole raggiungere tramite il server. Il server elenca gli indirizzi sorgente che quel client è autorizzato a utilizzare.

La coppia corrispondente di file di configurazione

Client, /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32

[Peer]
PublicKey = <server public key>
Endpoint = home.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.20.0/24
PersistentKeepalive = 25

Server, /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = <server private key>
Address = 10.8.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <laptop public key>
AllowedIPs = 10.8.0.2/32

Anche il router di casa deve avere un port forwarding, UDP 51820 verso 192.168.20.5, altrimenti l'handshake non inizia mai e il client registra Handshake for peer 1 did not complete after 5 seconds, retrying. Questa guida presuppone che questo passaggio sia già stato completato.

Quattro righe differiscono da una configurazione full tunnel standard, e ciascuna ha uno scopo preciso.

  • AllowedIPs = 10.8.0.0/24, 192.168.20.0/24 sul client, invece di 0.0.0.0/0, ::/0. Questo è uno split tunnel: la subnet del tunnel e la LAN domestica passano attraverso wg0, mentre tutto il resto continua a usare la route locale. La navigazione web non passa attraverso la connessione di casa, che in genere è ciò che serve quando si deve accedere soltanto al NAS.
  • AllowedIPs = 10.8.0.2/32 sul server, con un solo indirizzo invece di un intervallo. Scrivere 10.8.0.0/24 in quel punto consente a quel singolo client di usare qualsiasi indirizzo all'interno del tunnel. Se in seguito si aggiunge un secondo peer con un intervallo sovrapposto, il traffico viene inviato al peer configurato per ultimo, senza che venga visualizzato alcun errore.
  • PersistentKeepalive = 25 soltanto sul client. Il client si trova dietro NAT (network address translation) e il router elimina la mappatura UDP dopo uno o due minuti di inattività; di conseguenza, il server non riesce più a raggiungerlo. Il server ha un indirizzo pubblico e non richiede il keepalive.
  • Per ora non è presente alcuna riga DNS =. Aggiungerne una modifica la risoluzione dei nomi per l'intero computer client. La sezione DNS seguente spiega il funzionamento prima di attivarla.

Un full tunnel consente comunque di raggiungere la LAN, perché 0.0.0.0/0 corrisponde a ogni indirizzo. Tuttavia, instrada tutto il traffico attraverso il tunnel e introduce una collisione di subnet che non è possibile correggere dal client.

Perché la stessa subnet alle due estremità causa problemi

Scegli una subnet domestica utilizzata da pochissime altre reti, ad esempio 192.168.20.0/24 o 10.44.7.0/24. 192.168.1.0/24 e 192.168.0.0/24 sono le impostazioni predefinite di fabbrica della maggior parte dei router consumer. Prima o poi, quindi, il laptop si troverà su una rete Wi-Fi di un bar o di un hotel che utilizza esattamente quell’intervallo.

La collisione blocca la connessione e si manifesta in modo diverso nei due casi. Con uno split tunnel, wg-quick tenta di aggiungere una route per un prefisso già presente sull’interfaccia Wi-Fi, ip route add rifiuta l’operazione e l’interfaccia non si attiva:

RTNETLINK answers: File exists

Con un full tunnel, wg-quick installa regole di policy routing che escludono deliberatamente le route più specifiche della tabella principale. La route locale 192.168.1.0/24 ha la precedenza sul tunnel, quindi ogni pacchetto destinato alla LAN remota esce dal collegamento locale. Il tunnel è attivo, l’handshake funziona, ma il NAS non è raggiungibile. Rinumerare la LAN domestica è l’unica soluzione effettiva.

Trasformare il server in un router

ip route show default
printf 'net.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward

Il primo comando restituisce il nome effettivo dell'interfaccia LAN. Le immagini attuali usano nomi come enp1s0 o ens3, più raramente eth0; una regola di masquerade che indica l'interfaccia errata non corrisponde ad alcun pacchetto. L'ultimo comando dovrebbe stampare net.ipv4.ip_forward = 1. Un semplice sudo sysctl -w imposta lo stesso valore, ma il valore viene perso al riavvio successivo. Questo causa il classico problema per cui "funzionava fino a martedì".

Il forwarding deve inoltre attraversare il firewall. Su Ubuntu con ufw attivo, i pacchetti inoltrati vengono eliminati se DEFAULT_FORWARD_POLICY="ACCEPT" non è impostato in /etc/default/ufw. Docker imposta autonomamente la stessa policy. Pertanto, se sudo iptables -S FORWARD | head -1 stampa -P FORWARD DROP su un sistema in cui non hai configurato manualmente il firewall, significa che l'ha impostata Docker e che il traffico del tunnel richiede una regola di accept esplicita.

Perché le risposte non tornano

Se le regole da 1 a 3 sono corrette, il ping raggiunge effettivamente il NAS. Tuttavia non si vede alcuna risposta, perché il pacchetto di risposta non ha una route di ritorno. Il NAS risponde a 10.8.0.2, un indirizzo esterno alla propria subnet, quindi inoltra il pacchetto al gateway predefinito, il router di casa all'indirizzo 192.168.20.1. Quel router non conosce 10.8.0.0/24, quindi inoltra la risposta al proprio gateway predefinito, cioè la connessione Internet, dove il pacchetto viene scartato. La richiesta arriva, ma la risposta viene eliminata.

Opzione A: masquerade sul server WireGuard. Il server riscrive l'indirizzo sorgente di ogni pacchetto inoltrato con 192.168.20.5, il proprio indirizzo LAN. Il NAS vede quindi una richiesta proveniente da un host della propria subnet, risponde direttamente al server e il server annulla la riscrittura, quindi invia il pacchetto di risposta attraverso il tunnel. Non è necessario modificare gli altri host della LAN.

Inseriscila nel blocco [Interface] del server, in modo che la regola venga aggiunta e rimossa insieme all'interfaccia:

PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp1s0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o enp1s0 -j MASQUERADE

Su un host già gestito con nftables, inseriscila invece in /etc/nftables.conf:

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.8.0.0/24 oifname "enp1s0" counter masquerade
  }
}

Mantieni la parola chiave counter. Senza di essa, sudo nft list ruleset mostra la regola senza il conteggio dei pacchetti. Proprio quel conteggio indica se la regola viene utilizzata.

Masquerade offre anche un secondo vantaggio, meno evidente. Molti host eseguono un firewall che accetta connessioni soltanto dalla propria subnet. La condivisione file di Windows si comporta così per impostazione predefinita, come anche diversi pannelli di amministrazione dei NAS. Un pacchetto proveniente da 10.8.0.2 viene scartato dall'host di destinazione anche quando il routing è corretto. Dopo il masquerade, l'indirizzo sorgente appartiene alla LAN, quindi queste regole corrispondono. Lo svantaggio è che nei log di ogni host della LAN tutti i client del tunnel risultano come 192.168.20.5. Non è quindi possibile distinguerli e le regole specifiche per client sui dispositivi LAN non possono funzionare.

Opzione B: una route statica sul router di casa. Indica al router che 10.8.0.0/24 si trova dietro 192.168.20.5. Su un router Linux basta un comando:

sudo ip route add 10.8.0.0/24 via 192.168.20.5

I router consumer hanno una pagina chiamata Static Routes o Routing nelle impostazioni avanzate: destinazione 10.8.0.0, maschera 255.255.255.0, gateway 192.168.20.5. Salva la configurazione sul router, perché un ip route add eseguito su un host Linux viene perso al riavvio successivo.

In questo modo viene mantenuto l'indirizzo reale del client, quindi i log e le regole specifiche per client nella LAN restano significativi. È necessario un router che supporti le route statiche e la configurazione funziona soltanto per gli host che usano quel router come gateway predefinito. Ogni host con un firewall locale applicato alla subnet deve comunque avere una regola propria per 10.8.0.0/24. Inizia con il masquerade, perché non richiede modifiche al di fuori dell'host che già controlli, e passa alla route statica quando ti servono gli indirizzi reali dei client.

Come individuare quale dei quattro elementi non funziona

Parti dal client e procedi verso l'esterno. Ogni passaggio indica se il pacchetto è arrivato fino a quel punto.

Il pacchetto entra nel tunnel? Sul client:

ip route get 192.168.20.10

La risposta dovrebbe indicare dev wg0. Se indica l'interfaccia Wi-Fi, la regola 1 non è corretta e AllowedIPs del client non include la subnet LAN. Un ping: connect: Network is unreachable indica lo stesso problema.

I pacchetti arrivano al server? Esegui questo comando sul server, quindi esegui il ping del NAS dal client:

sudo tcpdump -ni wg0 icmp

Un percorso funzionante mostra IP 10.8.0.2 > 192.168.20.10: ICMP echo request, dove ICMP è l'Internet Control Message Protocol, il protocollo utilizzato da ping. Se non compare nulla, ma l'handshake è corretto, il problema riguarda la regola 2: AllowedIPs del server per quel peer non include 10.8.0.2. Di conseguenza, il pacchetto è stato scartato durante la decifratura, prima di raggiungere wg0.

I pacchetti escono verso la LAN? Sul server, monitorando il lato LAN:

sudo tcpdump -ni enp1s0 icmp

Se le richieste sono visibili su wg0, ma non compaiono qui, il problema riguarda la regola 3: l'inoltro è disabilitato oppure una regola FORWARD ha scartato il pacchetto. Se le richieste compaiono qui con origine 10.8.0.2, ma non arrivano risposte, il problema riguarda la regola 4: la risposta non ha una route di ritorno. Se le richieste compaiono qui con origine 192.168.20.5, ma non arrivano risposte, la regola di masquerade funziona e il sistema di destinazione sta rifiutando la richiesta. Controlla quindi il firewall sul NAS. Lo stesso percorso di verifica funziona per qualsiasi altro servizio: sostituisci icmp con port 445 oppure con la porta da controllare.

Riesco a raggiungere l'indirizzo IP, ma non il nome

ssh 192.168.20.10 funziona e ssh nas.home.arpa non funziona:

ssh: Could not resolve hostname nas.home.arpa: Name or service not known

Il tunnel non presenta problemi. La risoluzione dei nomi segue un percorso separato e il laptop continua a interrogare il resolver ricevuto dalla rete Wi-Fi locale. Quel resolver non conosce i nomi della rete domestica.

Perché i nomi della rete domestica funzionino, devono essere vere due condizioni. L'indirizzo del resolver deve trovarsi all'interno di AllowedIPs sul client; in caso contrario, la query DNS (domain name system) non entra mai nel tunnel. Inoltre, il resolver deve accettare una query con indirizzo di origine 10.8.0.2. Molti resolver domestici rifiutano queste richieste per impostazione predefinita: dnsmasq eseguito con local-service risponde soltanto alle query provenienti da una subnet collegata direttamente, mentre Pi-hole viene distribuito con una modalità di ascolto che consente soltanto le richieste locali. Una regola di masquerade nasconde il problema, perché dopo la riscrittura la query arriva da 192.168.20.5.

Sul client basta una riga:

DNS = 192.168.20.1

Su un client Linux sono necessari openresolv o un equivalente; in caso contrario wg-quick si interrompe con resolvconf: command not found. Prima di impostarlo, verifica il comportamento su un sistema con systemd-resolved: wg-quick registra esclusivamente quei server, quindi, mentre il tunnel è attivo, ogni lookup eseguito dal laptop viene inviato al resolver domestico, non soltanto quelli per i nomi della rete domestica. Verifica il risultato con resolvectl status wg0. Se vuoi risolvere i nomi domestici a casa e tutti gli altri localmente, si tratta di split DNS; la guida correzione del DNS tramite un tunnel WireGuard descrive la configurazione completa.

Nessun IP pubblico a casa? Usa un VPS come nodo intermedio

Se la pagina di stato del router mostra un indirizzo WAN nell'intervallo 100.64.0.0/10 oppure un indirizzo privato 192.168.x.x, la rete si trova dietro CGNAT (carrier grade network address translation) e nessun handshake proveniente da Internet può raggiungere la rete domestica. Un handshake in uscita continua a funzionare normalmente, quindi la soluzione consiste nell'aggiungere un terzo nodo con un indirizzo pubblico. Un piccolo VPS esegue il nodo hub e il server domestico si connette a esso in uscita.

Le quattro regole non cambiano. Ora si applicano su due hop, quindi la gestione degli indirizzi raddoppia.

  • Sul VPS, la voce peer del server domestico riceve AllowedIPs = 10.8.0.3/32, 192.168.20.0/24: il proprio indirizzo del tunnel e la subnet per la quale è autorizzato a inoltrare traffico.
  • Sul VPS, la voce peer del laptop resta AllowedIPs = 10.8.0.2/32.
  • Sul laptop, il peer del VPS riceve AllowedIPs = 10.8.0.0/24, 192.168.20.0/24, perché ora tutto il traffico passa dall'hub.
  • Sul server domestico, il peer del VPS riceve AllowedIPs = 10.8.0.0/24 e il server domestico gestisce PersistentKeepalive = 25, perché ora si trova sul lato dietro NAT.
  • Anche il VPS ha bisogno di net.ipv4.ip_forward = 1 e la sua catena di forwarding deve consentire wg0 a wg0, perché il traffico del laptop arriva ed esce dalla stessa interfaccia. Un firewall configurato per un VPS con full tunnel standard blocca esattamente questo traffico.

Se non hai ancora configurato il VPS, configurare WireGuard su un VPS illustra la generazione delle chiavi, il firewall e l'unità systemd. Il modello più generale per raggiungere una macchina che non può accettare connessioni in ingresso è descritto in aprire un reverse tunnel dietro CGNAT. Quando la gestione manuale degli indirizzi dei peer diventa scomoda, eseguire un router di subnet Tailscale svolge lo stesso compito di routing automatizzando la gestione degli indirizzi.

Rendere la configurazione persistente dopo un riavvio

sudo systemctl enable --now wg-quick@wg0
sudo systemctl enable --now nftables
sudo wg show

enable --now è il passaggio che molti saltano. Un wg-quick up wg0 eseguito manualmente scompare dopo il successivo aggiornamento del kernel e il riavvio. wg show dovrebbe elencare il peer con una riga latest handshake recente e contatori di trasferimento diversi da zero in entrambe le direzioni.

L'aggiunta successiva di un secondo client non richiede un riavvio, che disconnetterebbe tutti gli utenti attualmente connessi:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

wg-quick strip stampa la configurazione senza le chiavi comprese soltanto da wg-quick, mentre syncconf applica la differenza senza interrompere le sessioni attive. Aggiorna soltanto i peer. La modifica di Address o l'aggiunta di una nuova riga PostUp richiede comunque un arresto e un avvio completi.

FAQ

Perché posso eseguire il ping del server WireGuard, ma non raggiungo gli altri dispositivi della LAN domestica?

Il ping a 10.8.0.1 dimostra soltanto che il tunnel è attivo. Il problema riguarda il routing del resto della LAN. Il parametro AllowedIPs del client deve includere 192.168.20.0/24, altrimenti il pacchetto non entra nel tunnel. Sul server è necessario impostare net.ipv4.ip_forward su 1, altrimenti il server scarta i pacchetti non destinati a se stesso. Inoltre, la LAN deve avere una route verso 10.8.0.0/24. Esegui sudo tcpdump -ni enp1s0 icmp sul server durante il ping: se le richieste escono con origine 10.8.0.2 e non arrivano risposte, manca il percorso di ritorno.

È necessaria una route statica sul router domestico?

Solo se non utilizzi la regola di masquerade. Una regola di masquerade sul server WireGuard sostituisce l'indirizzo sorgente del traffico del tunnel con l'indirizzo LAN del server. Gli host della LAN rispondono così a un dispositivo che sanno già raggiungere e il router non viene coinvolto. L'alternativa è una route statica per 10.8.0.0/24 tramite l'indirizzo LAN del server. Questa soluzione è utile se vuoi visualizzare nei log degli host LAN gli indirizzi reali dei client o applicare regole firewall specifiche per client.

Perché la stessa subnet alle due estremità interrompe il tunnel?

Il laptop non può gestire due route per lo stesso prefisso. Se la rete locale assegna 192.168.1.0/24 e anche la LAN domestica usa 192.168.1.0/24, un tunnel diviso wg-quick up non funziona quando ip route add rifiuta l'operazione con RTNETLINK answers: File exists. Un tunnel completo si attiva comunque, ma wg-quick installa regole di policy che impediscono alle route più specifiche della tabella principale di avere effetto. Di conseguenza prevale la rete locale e la LAN remota resta irraggiungibile. Rinumera la LAN domestica usando una rete meno comune, ad esempio 192.168.20.0/24. Non esiste una correzione lato client.

Posso raggiungere il NAS tramite IP, ma non tramite nome. Che cosa manca?

La risoluzione dei nomi non segue automaticamente il tunnel. Aggiungi DNS = 192.168.20.1, il resolver domestico, al blocco [Interface] del client e verifica che l'indirizzo rientri nel parametro AllowedIPs del peer. In caso contrario, la query non entra nel tunnel. Verifica anche che il resolver accetti query provenienti dall'esterno della propria subnet, perché dnsmasq con local-service e la modalità di ascolto solo locale di Pi-hole le rifiutano entrambe. Una regola di masquerade sul server WireGuard risolve il problema sostituendo l'indirizzo sorgente della query.

La mia connessione domestica non ha un IP pubblico. Posso comunque raggiungere la LAN?

Sì, utilizzando un terzo nodo. In presenza di CGNAT, l'indirizzo WAN del router è privato. Nessun peer su Internet può quindi avviare un handshake verso il router, mentre un handshake in uscita funziona normalmente. Esegui WireGuard su un VPS con un indirizzo pubblico, configura il computer di casa perché si connetta a tale VPS tramite PersistentKeepalive = 25 e assegna al peer del computer di casa sul VPS un parametro AllowedIPs che contenga il relativo indirizzo del tunnel e 192.168.20.0/24. Sul VPS devi inoltre abilitare il forwarding e aggiungere una regola di forward che consenta a wg0 di raggiungere wg0.