Disconnetti la VPN, ping 1.1.1.1 risponde ancora e ogni risoluzione di nome resta appesa prima che la pagina alla fine si arrenda. Poi cat /etc/resolv.conf mostra un server dei nomi che è mai esistito solo dentro il tunnel, di solito il primo dell’elenco. Cancellare quella riga sembra risolvere per una decina di minuti, finché una sospensione, un roaming Wi-Fi o un riavvio non la rimettono. Il file che hai modificato non è l’impostazione; è una rappresentazione dello stato del collegamento che appartiene a un altro componente.

Perché una voce obsoleta costa secondi per ogni risoluzione

Il resolver di glibc percorre l’elenco dei server dei nomi in ordine e attende la scadenza di un timeout prima di provare il successivo, e resolv.conf(5) limita quell’elenco a tre voci. Metti un resolver lato tunnel come 10.8.0.1 in cima dopo che il tunnel è sparito e ogni risoluzione paga il timeout prima di ricadere su un server che risponde. Ecco perché il sintomo sembra una connessione morta e non un errore DNS: i browser si bloccano, scadono e talvolta servono un indirizzo in cache che poi diventa obsoleto.

Questo spiega anche perché la lamentela arriva come «internet è rotto». Un ping verso un indirizzo IP dimostra che il collegamento è a posto, il che fa sembrare il guasto dell’applicazione. L’elenco dei resolver è la prima cosa da leggere e l’ultima da modificare.

Il mito: resolv.conf è un file di impostazioni

Chiedi che cos’è davvero il percorso prima di cambiarlo:

ls -l /etc/resolv.conf
readlink -f /etc/resolv.conf

Su un host con systemd-resolved è un collegamento simbolico a un file stub che punta a 127.0.0.53, e i server veri vivono nello stato per collegamento che resolvectl stampa. Su un host con NetworkManager può essere un file che NetworkManager scrive dalla connessione attiva. Con alcuni client di fornitori è un file semplice riscritto sul posto alla connessione e, se sei sfortunato, mai ripristinato alla disconnessione. Sono tre proprietari diversi, e modificare i primi due a mano o non fa nulla o dura fino al prossimo evento di rete.

resolvectl status è la vista che dice la verità: server DNS per collegamento, domini di instradamento e se il collegamento del tunnel esiste ancora. resolvectl query example.com va oltre e mostra quale interfaccia ha risposto. Usa entrambi prima di toccare un file, e tieni presente che un browser con DNS sicuro proprio ignora tutto questo.

Trova il proprietario prima di modificare qualsiasi cosa

Di solito tre componenti competono per la stessa impostazione: systemd-resolved, NetworkManager e quello che il client VPN ha installato. Individua prima quello vivo:

systemctl is-active systemd-resolved
nmcli connection show --active
ps aux | grep -E "openvpn|wg-quick|vpn"

Se resolved è attivo e il collegamento simbolico punta al suo stub, il file globale è output generato e la tua modifica è cosmetica. Se NetworkManager possiede la connessione, i server appartengono al profilo di connessione, quindi la correzione è un cambio di proprietà con nmcli e non una modifica di file. Se è in esecuzione un demone del fornitore, solo il suo percorso di ripristino sopravvive alla connessione successiva.

Pulisci lo stato del collegamento lasciato dal client

Un client ucciso non può eseguire il suo hook di pulizia. SIGKILL non è intercettabile affatto, mentre SIGINT e SIGTERM lo sono, quindi un tunnel che «si è appena fermato» dopo un kill forzato spesso lascia al loro posto sia la registrazione dell’interfaccia sia la voce del resolver. Trova il PID preciso e invia il segnale solo a quello:

ps aux | grep -E "openvpn|wg-quick"
sudo kill <pid>
resolvectl revert tun0

Non ricorrere a pkill -f vpn o killall vpn prima di aver letto l’elenco completo delle corrispondenze. -f corrisponde all’intera riga di comando, quindi può terminare uno script wrapper, una sessione dell’editor o un processo non correlato il cui percorso contiene la stringa. Terminare il processo sbagliato a metà lavoro è il modo in cui un problema di resolver diventa un file perso.

resolvectl revert azzera la configurazione DNS a runtime di quel collegamento, che è più stretto di riavviare il resolver e molto più stretto di modificare il file globale. Se il collegamento del tunnel è sparito del tutto, systemctl restart NetworkManager ricostruisce lo stato della connessione ed è il passaggio a cui i thread di origine tornano continuamente. Attenzione a un gestore di servizi con Restart=always, perché può rimettere un client ucciso, e le sue impostazioni DNS, direttamente al loro posto.

L’altra direzione: DNS spinto che non è mai arrivato

L’immagine speculare della voce obsoleta è un tunnel senza alcun resolver utilizzabile. Un’opzione DNS nel profilo è una richiesta; il componente che gestisce la connessione deve consegnarla al resolver. Se il log mostra che il server è stato ricevuto ma il collegamento del tunnel non porta alcuna impostazione DNS, manca l’integrazione, non il server.

Prova la consegna facendola a mano, il che separa «il server è sbagliato» da «nessuno l’ha applicata»:

resolvectl dns tun0 10.10.10.10
resolvectl domain tun0 ~.

Il dominio di instradamento catch-all manda ogni nome a quel collegamento, che è ciò che vuole un client a tunnel completo e ciò che il DNS diviso non deve usare. Queste impostazioni svaniscono alla connessione successiva. Per renderle persistenti in NetworkManager, disattiva il DNS automatico, imposta il server sulla connessione e aggiungi il dominio:

nmcli connection modify office ipv4.ignore-auto-dns yes
nmcli connection modify office ipv4.dns 10.10.10.10
nmcli connection modify office ipv4.dns-search "~."

Per un tunnel aziendale che deve rispondere solo ai nomi interni, elenca quelle zone con una tilde iniziale invece del catch-all, così i nomi pubblici continuano a usare il resolver locale.

Aggiramenti che diventano la prossima interruzione

Copiare resolv.conf prima di connettersi e ripristinarlo dopo è una riga legittima in un runbook, ed è un aggiramento e non una riparazione. Fallisce esattamente quando conta, perché un crash o un riavvio forzato saltano il ripristino. Annotalo come aggiramento perché la persona successiva non ci costruisca sopra.

Disattivare systemd-resolved e codificare a mano server pubblici è l’altra mossa popolare. Rende connessione e disconnessione prevedibili e toglie il DNS per collegamento a ogni altra rete, il che rompe il DNS diviso per i nomi interni e vanifica lo scopo di un tunnel pensato per tenere le query al suo interno. Installare resolvconf e fissare server pubblici costa lo stesso con uno strato in più. Tratta l’uno o l’altro come diagnosi: se ripristina la navigazione, hai imparato che è colpevole l’integrazione del resolver, non che i server pubblici siano corretti.

La correzione duratura è un proprietario per strato: decidi quale componente possiede il DNS del collegamento del tunnel e quale il valore globale predefinito, scrivilo e togli gli altri dal percorso. Poi verifica dopo una disconnessione con un nome che solo la VPN risolve. Se un nome privato risponde ancora, la registrazione non è stata rimossa; se non si risolve nulla, il file punta a un server che non esiste più. Entrambe le cose si vedono in resolvectl prima di aprire un browser.

Articoli correlati