DNS su WireGuard: 3 problemi e come risolverli
Il tunnel WireGuard è attivo ma i nomi non si risolvono o le query passano dal router locale? Scopri i tre guasti DNS e la correzione per ciascuno.
Perché il DNS si interrompe non appena il tunnel WireGuard si attiva
Il DNS su WireGuard non funziona in tre modi diversi, e ognuno richiede una correzione specifica. A volte non viene risolto alcun nome. In altri casi i nomi vengono risolti, ma le query escono dal computer senza passare nel tunnel. In altri ancora, il gestore del resolver del client sovrascrive l'impostazione pochi secondi dopo l'avvio dell'interfaccia. Il tunnel è quasi sempre estraneo al problema. La causa è la riga che indica al client quale resolver interrogare e il routing che determina il percorso dei pacchetti diretti a quel resolver.
WireGuard trasporta pacchetti IP e non gestisce il DNS (domain name system, il servizio che converte nomi come example.com in indirizzi IP). La riga DNS = in un blocco client [Interface] non è un'impostazione di WireGuard. Viene letta da wg-quick, il wrapper della shell che attiva l'interfaccia, e wg-quick modifica quindi la configurazione del resolver del client mentre il tunnel è attivo, per ripristinarla su wg-quick down. Di conseguenza, ogni problema descritto di seguito riguarda il routing o wg-quick, mai la crittografia. Se il tunnel non è ancora configurato, inizia da una VPN WireGuard self-hosted sul tuo VPS e torna a questa pagina in seguito.
Verifica che il tunnel funzioni correttamente prima di intervenire sul DNS.
sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1wg show dovrebbe elencare il peer con un latest handshake recente ed entrambi i ping dovrebbero ricevere risposta. Se ping 1.1.1.1 va in timeout, il problema riguarda il forwarding o il NAT (network address translation), non il DNS, e nessuna modifica alla configurazione del resolver sarà utile. Tutti gli esempi qui riportati usano 10.8.0.0/24 come subnet del tunnel e 10.8.0.1 come indirizzo del tunnel del server. Sostituiscili con i valori del tuo ambiente.
Errore uno: non viene risolto nulla perché il resolver non risponde
Il sintomo è preciso. ping 1.1.1.1 funziona e curl https://example.com restituisce:
curl: (6) Could not resolve host: example.comInterroga direttamente il resolver del tunnel dal client. dig appartiene al pacchetto dnsutils su Ubuntu e Debian.
dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.comIl primo comando restituisce un indirizzo. Questo dimostra che i pacchetti raggiungono Internet attraverso il tunnel. Il secondo non restituisce nulla e stampa ;; communication timed out; no servers could be reached. La diagnosi è completa: il client usa 10.8.0.1 e 10.8.0.1 non risponde sulla porta UDP 53.
Le cause possibili sono due. Sul server non è in esecuzione alcun resolver oppure il firewall del server elimina la richiesta prima che arrivi. Verifica entrambe le condizioni sul server.
sudo ss -ulnp | grep ':53'
sudo nft list rulesetUn resolver in esecuzione e associato correttamente mostra una riga con 10.8.0.1:53 o 0.0.0.0:53. Su Ubuntu il problema più comune è 127.0.0.53:53: si tratta dello stub listener di systemd-resolved, che usa un indirizzo di loopback e non è raggiungibile intenzionalmente da altri computer. Configurare un client VPN per usare un server il cui unico resolver è questo stub produce esattamente questo timeout.
La soluzione consiste in un resolver in ascolto sull'indirizzo del tunnel e in una regola del firewall che consenta ai peer di raggiungerlo.
sudo apt update && sudo apt install -y unbound
printf 'server:\n interface: 10.8.0.1\n access-control: 10.8.0.0/24 allow\n' \
| sudo tee /etc/unbound/unbound.conf.d/wireguard.conf
sudo systemctl restart unbound
sudo ss -ulnp | grep '10.8.0.1:53'Quindi apri la porta solo per il traffico del tunnel. Con nftables, aggiungi queste due righe alla catena input in /etc/nftables.conf e ricarica la configurazione con sudo systemctl reload nftables.
udp dport 53 iifname "wg0" accept
tcp dport 53 iifname "wg0" acceptCon ufw, sudo ufw allow in on wg0 to any port 53 svolge la stessa funzione. Non esporre mai la porta 53 a Internet. Gli scanner individuano in pochi giorni un resolver ricorsivo aperto e lo usano per amplificare attacchi di denial of service. Il provider noterà questo traffico prima di te.
Esegui di nuovo dig +short @10.8.0.1 example.com dal client. Un indirizzo nell'output indica che il percorso verso il resolver funziona. A questo punto il client deve solo utilizzarlo. Aggiungi la riga al blocco [Interface] del client e riavvia l'interfaccia con sudo wg-quick down wg0 && sudo wg-quick up wg0.
[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1Errore due: perdite DNS, perché uno split tunnel non instrada il resolver
Questo problema è peggiore, perché tutto sembra funzionare. I nomi vengono risolti, le pagine vengono caricate e le query viaggiano in chiaro sulla rete locale che non volevi considerare attendibile.
A causarlo sono due configurazioni. La prima è un client con AllowedIPs = 0.0.0.0/0, ::/0 e senza una riga DNS =. wg-quick installa la route predefinita nella propria tabella di routing e aggiunge una regola con suppress_prefixlength 0. In questo modo mantiene intenzionalmente attive le route locali più specifiche, così la macchina può ancora raggiungere la stampante. Il resolver appreso dal client tramite DHCP, in genere il router all'indirizzo 192.168.1.1, corrisponde a una di queste route locali. Il traffico passa attraverso il tunnel. La rete locale riceve comunque l'elenco completo dei nomi cercati.
La seconda è uno split tunnel: AllowedIPs = 10.8.0.0/24 con DNS = 9.9.9.9. Poiché 9.9.9.9 non è incluso in AllowedIPs, il client non dispone di una route verso quell'indirizzo attraverso il tunnel. La query esce quindi dal collegamento locale, esattamente come nel primo caso.
Verifica quale resolver risponde davvero. whoami.akamai.net è un nome di test pubblico che restituisce l'indirizzo IP del resolver ricorsivo che ha effettuato la richiesta. Puoi quindi confrontare la risposta con l'indirizzo pubblico del server.
resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53resolvectl status stampa un blocco per ogni collegamento. Se il blocco del collegamento Ethernet o wireless mostra ancora Current DNS Server: 192.168.1.1, mentre il blocco wg0 non ne mostra alcuno, si tratta di una perdita. Se dig +short whoami.akamai.net restituisce l'indirizzo della tua connessione a banda larga domestica invece di quello del server, la verifica dal lato remoto è confermata. La riga tcpdump fornisce la prova definitiva: in un'uscita corretta, ogni pacchetto sulla porta 53 passa attraverso wg0; in caso di perdita, passa attraverso wlan0 o enp3s0.
La correzione richiede due interventi, ed entrambi sono necessari. Imposta DNS su un indirizzo appartenente al tunnel e assicurati che tale indirizzo sia incluso in AllowedIPs.
[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/1610.8.0.1 appartiene a 10.8.0.0/24, quindi la query viene cifrata e inviata al server. Se vuoi usare un resolver pubblico con uno split tunnel, aggiungilo come host route: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. I pacchetti passeranno quindi attraverso il tunnel, ma la rete locale potrà comunque vedere che hai scelto quel provider, sulla base delle sessioni precedenti. Un resolver gestito autonomamente evita questo problema.
L'assegnazione del resolver è una delle differenze visibili tra WireGuard configurato manualmente e una mesh coordinata. Rientra nel compromesso descritto in WireGuard a confronto con Tailscale. L'esecuzione di un server di controllo Headscale self-hosted fornisce questo coordinamento senza affidare il materiale delle chiavi a terzi.
Errore tre: resolvconf e systemd-resolved entrano in conflitto sui client Linux
I client macOS, Windows, iOS e Android applicano DNS = tramite l'app ufficiale e causano pochi problemi. Su Linux l'impostazione viene applicata da uno script shell che deve determinare quale dei diversi gestori dei resolver è in uso.
Il primo errore è evidente. sudo wg-quick up wg0 si interrompe con:
resolvconf: command not foundwg-quick richiama resolvconf, ma il file binario non è installato. Installa l'implementazione che comunica con systemd-resolved, quindi riattiva l'interfaccia.
sudo apt install -y openresolv
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0Il secondo errore è silenzioso ed è quello che può farti perdere un'intera serata. L'interfaccia si attiva, resolvectl status wg0 mostra correttamente DNS Servers: 10.8.0.1, ma le ricerche continuano a usare il resolver precedente. systemd-resolved mantiene un elenco separato di resolver per ogni collegamento e sceglie un collegamento per ogni query. Se nessun collegamento è contrassegnato come route predefinita per i nomi, continua a usare il resolver del collegamento wireless, perché quel collegamento contiene un dominio di ricerca e il tuo no.
Imposta il resolver e assegna la route predefinita nello stesso passaggio. %i viene sostituito con il nome dell'interfaccia, quindi questo blocco funziona senza modifiche su qualsiasi interfaccia.
[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %iElimina la riga DNS = quando usi PostUp in questo modo. In caso contrario, due meccanismi scrivono lo stato del resolver e solo uno dei due esegue la pulizia successiva. L'argomento ~. è la parte importante: contrassegna wg0 come dominio di routing per ogni nome, quindi systemd-resolved invia tutte le query a quel collegamento invece di sceglierne uno per ogni query. Verifica il risultato.
resolvectl status wg0L'output corretto contiene DNS Servers: 10.8.0.1 e Default Route: yes. Se Default Route restituisce no, la parte resolvectl domain non è stata eseguita e il sistema è tornato alla selezione del collegamento.
Vale la pena citare un altro caso. Se /etc/resolv.conf è un file reale anziché un collegamento simbolico a /run/systemd/resolve/stub-resolv.conf, un altro componente ne è il proprietario, in genere NetworkManager o un runtime per container. Esegui ls -l /etc/resolv.conf prima di eseguire altre attività di debug, perché uno strumento che riscrive quel file a ogni modifica della rete annullerà il lavoro eseguito nel momento meno opportuno.
L'aggiornamento: il resolver con filtraggio di tua gestione attraverso il tunnel
Quando le query attraversano il tunnel in modo affidabile, il resolver all'estremità remota diventa un punto di controllo. L'esecuzione di AdGuard Home in quel punto fornisce a ogni dispositivo connesso il filtraggio tramite blocklist e un registro delle query, senza software client e senza configurazioni per singolo dispositivo. Lo script ufficiale di installazione, verificato a luglio 2026, consiste in una sola riga.
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -vLa procedura guidata di configurazione è in ascolto sulla porta 3000 alla prima esecuzione. Raggiungila attraverso il tunnel all'indirizzo http://10.8.0.1:3000 invece di esporre pubblicamente quella porta e, nella procedura guidata, imposta sia l'indirizzo di ascolto DNS sia l'indirizzo di ascolto dell'amministrazione su 10.8.0.1. Se unbound del primo errore è ancora in ascolto sullo stesso indirizzo, arrestalo prima con sudo systemctl disable --now unbound, perché due processi non possono associare la porta UDP 53 allo stesso indirizzo e il secondo processo termina con listen udp 10.8.0.1:53: bind: address already in use.
Le configurazioni dei client non richiedono modifiche se contengono già DNS = 10.8.0.1. Il registro delle query mostrerà ora ogni ricerca eseguita da ogni peer. Questa è una scelta concreta per la privacy, non un vantaggio gratuito: trasferisci la fiducia dal tuo provider Internet a te stesso e sei tu a dover mantenere aggiornato quel server. Un server esposto a Internet deve avere prima le protezioni di base, che sono descritte in i primi dieci minuti su un nuovo VPS.
FAQ
Perché il tunnel WireGuard si connette, ma i nomi non vengono risolti?
Il tunnel trasporta pacchetti, ma non gestisce i nomi. Un tunnel funzionante con risoluzioni non funzionanti indica quindi che il resolver configurato non risponde. Esegui dig +short @10.8.0.1 example.com dal client. Una risposta communication timed out indica che nessun resolver è in ascolto sull'indirizzo del tunnel, spesso perché lo stub di systemd-resolved è associato solo a 127.0.0.53, oppure che il firewall del server sta scartando il traffico UDP sulla porta 53 in arrivo su wg0. Correggi prima il listener, quindi apri la porta solo per wg0.
Come verifico se il DNS presenta perdite attraverso WireGuard?
Esegui sudo tcpdump -ni any -c 10 port 53 sul client e controlla la colonna dell'interfaccia durante la navigazione. Ogni pacchetto dovrebbe passare su wg0. Se i pacchetti compaiono sull'interfaccia wireless o ethernet, le query stanno uscendo in chiaro. dig +short whoami.akamai.net fornisce una seconda verifica, perché risponde con l'indirizzo pubblico del resolver ricorsivo che ha eseguito la query. Una risposta che non contiene l'indirizzo del server conferma quindi la perdita.
La riga DNS = è necessaria se uso un tunnel parziale?
Sì. Inoltre, l'indirizzo del resolver deve trovarsi all'interno di AllowedIPs, altrimenti il client non ha una route per raggiungerlo. Con AllowedIPs = 10.8.0.0/24, un resolver su 10.8.0.1 è incluso e la query viene cifrata. Un resolver pubblico come 9.9.9.9 non è incluso, quindi la query esce attraverso il collegamento locale anche se la riga DNS sembra corretta.
Perché resolvectl mostra il server corretto, ma le risoluzioni usano comunque un altro server?
systemd-resolved mantiene un elenco di resolver per ogni collegamento e sceglie un collegamento per ogni query. Di conseguenza, una voce corretta su wg0 viene ignorata quando un altro collegamento contiene la route predefinita per i nomi. Aggiungi PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. al blocco [Interface] del client e rimuovi la riga DNS =. A quel punto resolvectl status wg0 dovrebbe riportare Default Route: yes.
Quale client devo correggere per primo quando più client presentano problemi?
Correggi un client Linux, perché è l'unica piattaforma che mostra il meccanismo. resolvectl status e tcpdump indicano quale resolver ha risposto e quale interfaccia ha trasportato il pacchetto. Le app per telefono e desktop applicano gli stessi valori DNS e AllowedIPs senza mostrare i dettagli della configurazione. Quando il client Linux funziona, puoi quindi copiare una configurazione già verificata.