1,670 24/03/2026 07/04/2026 7 min

Il sintomo arriva spesso così: il client si connette, ma una parte del traffico continua a uscire dalla rete locale. In parallelo, i log mostrano AllowedIPs conflict oppure una risoluzione DNS incoerente tra più client WireGuard.

In questo articolo partiamo da quel caso concreto. Prima sistemiamo il routing split. Poi eliminiamo il DNS leak. Alla fine verifichiamo l’MTU, che è il dettaglio che rovina una VPN “quasi” funzionante.

Scenario reale: un server WireGuard ospitato su una VPS Linux, due client attivi in contemporanea, e un terzo device mobile che deve vedere solo la subnet interna. Il problema nasce quando gli stessi IP o le stesse rotte vengono assegnati a più peer.

Prerequisiti

  • Un server Linux con WireGuard già installato.
  • Accesso root o sudo.
  • Un client Linux, macOS o Windows per i test.
  • Un DNS interno o un resolver affidabile da forzare nel tunnel.
  • Un editor di testo e accesso ai log del server.

Note: userò esempi con wg0, subnet 10.8.0.0/24 e due client. Adatta gli indirizzi alla tua rete.

Step 1 — Leggere il sintomo nei log e capire se è routing o DNS

Il primo controllo non è la config. È il comportamento.

Se il tunnel sale ma il traffico resta fuori, controlla due segnali:

  • ping verso un host interno fallisce;
  • il browser risolve nomi pubblici con il DNS dell’ISP invece che con quello previsto.

Su Linux, guarda il peer e lo stato del tunnel.

sudo wg show
ip route show table main
resolvectl status 2>/dev/null || cat /etc/resolv.conf

# Output:

peer: xxxxxxxxxx
  allowed ips: 10.8.0.2/32, 10.8.0.0/24
...
default via 192.168.1.1 dev eth0
nameserver 1.1.1.1

Perché funziona: separa subito il problema di routing dal problema DNS, invece di correggere la configurazione alla cieca.

Nota cross-distro: su systemd puoi usare resolvectl; su distribuzioni senza systemd, verifica /etc/resolv.conf o il resolver del network manager.

Step 2 — Correggere gli AllowedIPs per evitare conflitti tra client multipli

Il conflitto nasce quando due peer condividono la stessa rotta o la stessa subnet. WireGuard usa AllowedIPs sia come filtro sia come tabella di routing. Un errore qui rompe tutto.

Ogni peer deve avere un IP univoco. Ogni client deve ricevere solo la rotta che gli serve.

# /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY

# Client laptop
[Peer]
PublicKey = LAPTOP_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

# Client phone
[Peer]
PublicKey = PHONE_PUBLIC_KEY
AllowedIPs = 10.8.0.3/32

# Output:

interface: wg0
  public key: ...
peer: ...
  allowed ips: 10.8.0.2/32
peer: ...
  allowed ips: 10.8.0.3/32

Perché funziona: un indirizzo /32 per peer elimina l’ambiguità e impedisce che un client “rubI” la rotta dell’altro.

Warning: non assegnare a due peer lo stesso AllowedIPs. WireGuard accetta la config, ma il routing diventa imprevedibile.

Note: se ti serve una subnet interna raggiungibile da tutti, annunciala dal server verso i client, non tra i peer.

Step 3 — Impostare il routing split in modo esplicito

Per evitare che tutta la navigazione passi nel tunnel, limita le rotte ai soli prefissi necessari. È il classico split tunnel, ma va fatto con precisione.

Un client che deve raggiungere solo 10.8.0.0/24 e 192.168.50.0/24 non deve avere il default route nel tunnel.

# Client: /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.2/32
PrivateKey = LAPTOP_PRIVATE_KEY
DNS = 10.8.0.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.50.0/24
PersistentKeepalive = 25

# Output:

ip route show
10.8.0.0/24 dev wg0
192.168.50.0/24 dev wg0
default via 192.168.1.1 dev eth0

Perché funziona: il traffico destinato alle reti interne entra nel tunnel, mentre il resto continua a usare la connessione locale.

Note cross-distro: su Windows l’effetto è analogo, ma la GUI può aggiungere o rimuovere rotte in modo meno trasparente. Verifica sempre con route print.

Step 4 — Chiudere il DNS leak forzando il resolver nel tunnel

Il DNS leak è il problema più sottovalutato. La VPN sembra attiva, ma le query finiscono a un resolver pubblico o al router di casa.

Se usi systemd-resolved, puoi spingere il DNS del tunnel per interfaccia. Se usi NetworkManager, conviene impostarlo nel profilo della connessione WireGuard.

sudo resolvectl dns wg0 10.8.0.1
sudo resolvectl domain wg0 '~.'
sudo resolvectl flush-caches

# Output:

Link 5 (wg0): 10.8.0.1

Perché funziona: il dominio speciale ~. dice al resolver di usare quell’interfaccia per tutte le query che passano dal tunnel.

Se preferisci NetworkManager:

nmcli connection modify wg0 ipv4.dns 10.8.0.1 ipv4.ignore-auto-dns yes
nmcli connection up wg0

# Output:

Connection successfully activated

Warning: non basta scrivere DNS = 10.8.0.1 nel file WireGuard se il sistema ignora quel dato. Il supporto dipende dal client e dal gestore di rete.

Step 5 — Verificare l’MTU quando ping e browsing falliscono a metà

Se il tunnel si connette ma alcune pagine non aprono, o i download si bloccano su pacchetti grandi, l’MTU è il sospetto principale. Con WireGuard, 1420 è spesso un buon punto di partenza, ma non è universale.

Un MTU troppo alto crea frammentazione o black hole. Uno troppo basso degrada le prestazioni inutilmente.

ip link show wg0
ping -M do -s 1372 10.8.0.1

# Output:

2: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
1372 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=12.4 ms

Perché funziona: con ping -M do verifichi il percorso senza frammentazione. Se fallisce, l’MTU o il path underlay sono il problema.

Se noti perdita di pacchetti o siti che si aprono a metà, prova a scendere.

# /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
MTU = 1380

# Output:

link/none wg0 mtu 1380

Note: su alcuni provider VPS con overhead aggiuntivo, valori tra 1360 e 1400 sono più stabili di 1420.

Step 6 — Gestire più client senza collisioni operative

Con più client attivi, il problema non è solo l’IP. È anche la gestione delle rotte e delle abilitazioni lato server.

Se un laptop e un telefono devono accedere a sottoreti diverse, separa i profili. Non riusare la stessa chiave. Non riusare lo stesso endpoint logico.

wg genkey | tee laptop.key | wg pubkey > laptop.pub
wg genkey | tee phone.key | wg pubkey > phone.pub

# Output:

laptop.pub
phone.pub

Perché funziona: chiavi diverse e IP diversi rendono chiara la mappatura peer-dispositivo.

Se vuoi revocare un solo device, rimuovi il relativo peer e ricarica la config.

sudo wg set wg0 peer PHONE_PUBLIC_KEY remove
sudo wg show wg0

# Output:

peer: LAPTOP_PUBLIC_KEY
peer: ...

Note cross-distro: su sistemi con wg-quick@wg0, la ricarica completa può richiedere systemctl restart wg-quick@wg0. Su container o appliance leggere la documentazione del vendor.

Verifica finale

A questo punto fai tre controlli, in questo ordine:

  1. Ogni peer ha un AllowedIPs univoco.
  2. Le rotte sul client contengono solo le subnet necessarie.
  3. Il DNS del sistema usa il resolver previsto dal tunnel.

Usa questi comandi:

wg show
ip route get 192.168.50.10
resolvectl query example.com 2>/dev/null || nslookup example.com

# Output:

192.168.50.10 dev wg0 src 10.8.0.2
example.com: 93.184.216.34

Se il traffico interno esce su wg0 e il DNS risponde dal resolver atteso, il problema è risolto.

Tip: prova anche un traceroute verso una risorsa interna. Se il primo hop è il tunnel, il routing split è coerente.

Troubleshooting

1) RTNETLINK answers: File exists

Causa: due peer o due client stanno annunciando la stessa rotta, spesso con AllowedIPs duplicati.

Fix:

sudo wg show
sudoedit /etc/wireguard/wg0.conf
sudo systemctl restart wg-quick@wg0

# Output:

Removed existing route conflict

Perché funziona: il restart forza il ricalcolo delle rotte dopo aver reso univoci gli IP.

2) DNS leak detected

Causa: il resolver del sistema continua a usare l’interfaccia fisica invece del tunnel.

Fix:

sudo resolvectl dns wg0 10.8.0.1
sudo resolvectl domain wg0 '~.'
sudo resolvectl flush-caches

# Output:

Link wg0 now provides default route for DNS

Perché funziona: forzi il resolver a preferire il DNS del tunnel per tutte le query.

3) Handshake did not complete after 5 seconds

Causa: endpoint errato, porta bloccata, oppure MTU troppo aggressivo che spezza il traffico iniziale.

Fix:

sudo wg set wg0 peer SERVER_PUBLIC_KEY endpoint vpn.example.com:51820
sudo ip link set dev wg0 mtu 1380

# Output:

latest handshake: 2 seconds ago

Perché funziona: correggi l’indirizzo del server e riduci l’MTU per attraversare path con overhead maggiore.

Conclusione

Quando WireGuard sembra “attivo ma non affidabile”, il colpevole è quasi sempre uno tra routing, DNS e MTU. L’errore vero raramente è il tunnel in sé.

Il prossimo passo concreto è creare un profilo separato per ogni device e testarlo con ip route get, resolvectl e un ping con frammentazione disabilitata. Se uno dei tre fallisce, hai già il punto esatto dove intervenire.