Perché resolv.conf mostra il DNS della tua VPN ma le risoluzioni lo ignorano
Su un host con resolved il file è una vista, non lo stato. Segui lo stub, i server per collegamento e la riga nsswitch per capire quale usa davvero una risoluzione.
Nei log nulla sembra sbagliato: l'interfaccia è attiva, il resolver riporta il server DNS della VPN e il file su disco lo elenca. Eppure un nome host interno viene ancora risolto tramite il router locale. Le tre affermazioni non si contraddicono, perché il file, lo stato per collegamento e il percorso della risoluzione sono oggetti diversi che per caso condividono un nome. Quello che segue è il percorso che una query compie davvero su un host con systemd-resolved.
Tre oggetti chiamati resolv.conf
Su un host con resolved, /etc/resolv.conf è di solito un collegamento simbolico a /run/systemd/resolve/stub-resolv.conf. Quel bersaglio contiene l'indirizzo di un listener stub locale, 127.0.0.53, più i domini di ricerca calcolati da resolved. È una vista dello stato, non lo stato stesso.
Lo stato vive nella configurazione per collegamento di resolved, ed è per questo che resolvectl status può contraddire il file e avere comunque ragione. Ogni collegamento porta i propri server e i propri domini di instradamento, e lo stub consulta quei dati quando arriva una query. Il manuale di systemd-resolved descrive i file generati e il modello per collegamento; la separazione tra vista e stato è la parte da ricordare. Modificare il bersaglio del collegamento simbolico cambia ciò che leggono i client tradizionali, non ciò che sa il resolver.
Un terzo oggetto, /run/systemd/resolve/resolv.conf, appiattisce ogni collegamento in un'unica lista di server. Un programma puntato a quel file invia le query direttamente ai server elencati e salta lo stub, quindi la politica per collegamento non vale più per lui. Due programmi sulla stessa macchina possono quindi rispondere allo stesso nome in modo diverso, e nessuno dei due è guasto.
Segui una risoluzione attraverso NSS
glibc legge /etc/nsswitch.conf per decidere chi risponde a un nome. Una riga hosts che contiene resolve instrada la domanda verso nss-resolve, che interroga resolved via D-Bus e riceve la risposta per collegamento. Una riga con solo files dns invia la query all'indirizzo che /etc/resolv.conf detiene.
Questa sola riga spiega la maggior parte dei disaccordi tra un browser e dig. dig legge resolv.conf direttamente e non tocca mai NSS, quindi prova lo stub o un server a monte invece del percorso usato dall'applicazione. getent hosts internal.example passa per NSS, e confrontare la sua risposta con quella di dig è la prima misura utile.
Le applicazioni che includono un proprio resolver, o che parlano DNS su HTTPS con un endpoint fisso, aggirano entrambi i percorsi. Nulla in resolv.conf o nello stato di resolved le vincola.
Controlla chi possiede il file e verso cosa punta
Leggi la catena di collegamenti prima di cambiare qualcosa, perché la proprietà decide quale file è autorevole. Ogni comando qui sotto legge solo lo stato.
stat -c '%N' /etc/resolv.conf
resolvectl status --no-pager
grep '^hosts' /etc/nsswitch.conf
ls -l /run/systemd/resolve/
La prima riga stampa il collegamento e il suo bersaglio insieme, e un file normale posseduto da uno script VPN significa che il resolver non tratta mai quella scrittura come input. L'output di stato elenca i server per collegamento più i domini di instradamento che decidono dove va ogni query. La riga nsswitch dice se lo stub viene consultato del tutto, quindi un indirizzo stub nel file senza resolve lì significa che le query raggiungono il listener locale mentre nulla gestisce la separazione. Anche quell'ultimo elenco conta, perché un host senza stub-resolv.conf non esegue la disposizione descritta qui.
Se la catena termina in un file gestito da un altro pacchetto, il client VPN e quel pacchetto sono i due proprietari da riconciliare. Sostituire il collegamento scarta il lavoro di un proprietario e lascia quello dell'altro al suo posto.
Ripara dal proprietario del collegamento
Una connessione VPN dovrebbe registrare i propri server e i propri domini sul proprio collegamento, poi ritirarli alla disconnessione. L'integrazione resolved di NetworkManager e l'helper proprio di un client funzionano così; uno script che riscrive solo resolv.conf no.
Su un collegamento già esistente, la configurazione a runtime mostra il meccanismo. resolvectl dns tun0 10.40.0.53 allega un server, e resolvectl domain tun0 '~corp.example' allega un dominio di instradamento. La tilde è il carattere portante: confina le query di quel suffisso a questo collegamento e lascia in pace tutto il resto, mentre lo stesso valore senza di essa diventa un dominio di ricerca e la separazione svanisce. Quegli indirizzi sono esempi da laboratorio, non una configurazione persistente. Conferma con resolvectl query host.corp.example e leggi quale collegamento ha risposto.
Un server registrato ha comunque bisogno di una rotta. Quando la query raggiunge il collegamento giusto e va in timeout, il guasto è nella raggiungibilità attraverso il tunnel, non nella proprietà del resolver.
Come appare uno stato funzionante
Un risultato sano è coerente in tutte e tre le viste: i server per collegamento corrispondono a ciò che la VPN ha distribuito, i domini di instradamento coprono solo suffissi interni, e l'applicazione che conta risolve un nome interno mentre un nome pubblico segue ancora il percorso locale. Una query riuscita dimostra meno di questa concordanza.
Poi disconnetti e ripeti entrambe le query. Un client che lascia i propri domini registrati dopo lo smontaggio produce una macchina che fallisce le risoluzioni interne ore dopo, senza tunnel aperto e senza causa evidente.