scutil --dns stampa la configurazione del resolver che macOS consulta davvero, non l’unico server DNS che hai digitato in un pannello delle impostazioni. L’output è più lungo di quanto la maggior parte delle persone si aspetti, perché il sistema tiene blocchi di resolver separati per il percorso predefinito, per le interfacce con scope e per l’inoltro specifico per dominio. Il blocco in cima all’output non è necessariamente quello che risponde alla query. Se un nome privato si risolve in ufficio e fallisce nel momento in cui la VPN sale, il disallineamento è nelle regole di corrispondenza e nelle rotte, non nell’indirizzo del server. Leggi prima l’ordine, poi dimostra la risposta con una ricerca reale.

Leggi l’ordine dei blocchi prima degli indirizzi

Ogni voce si apre con resolver #N ed elenca nameserver[0], a volte if_index, una riga flags, reach e, quando il blocco non è un semplice default, un domain e una lista search domain. Il resolver numero 1 senza dominio è il default che gestisce i nomi pubblici. Tutto ciò che porta Scoped nei suoi flag è legato all’interfaccia nominata da if_index, e tutto ciò che è marcato Supplemental vale solo per i domini elencati sotto di esso.

La selezione è corrispondenza di suffisso. Per un nome come intranet.corp.example, macOS preferisce il resolver la cui voce domain è il suffisso corrispondente più lungo, quindi un blocco con domain : corp.example batte il default anche quando sta molto in basso nell’output. order risolve i pareggi tra domini della stessa lunghezza. Un primo sguardo raramente richiede di più: l’intero output quando vuoi leggere un blocco da un capo all’altro, le prime righe per imparare l’ordine dei blocchi e una passata filtrata che stampa le intestazioni dei blocchi accanto alle righe dei campi. I blocchi con scope compaiono sotto la propria intestazione e si leggono come una continuazione della lista sopra di essi, quindi tieni un’intestazione sotto gli occhi ogni volta che citi l’output.

scutil --dns
scutil --dns | sed -n '1,45p'
scutil --dns | grep -nE '^resolver #|^DNS configuration'
scutil --dns | grep -nE 'resolver #[0-9]+|if_index|domain|flags|nameserver'

Abbina if_index all’interfaccia del tunnel

Un indice è utile solo se puoi nominare l’interfaccia che gli sta dietro. scutil --nwi elenca le informazioni di rete che il sistema detiene, inclusa l’interfaccia principale e la raggiungibilità, mentre ifconfig -l ti dà i nomi, dove utun0 fino a utun9 sono i candidati tunnel che un client crea di solito. Apple usa scutil --dns come proprio esempio di ispezione nella guida al deployment, e documenta come Network Extension possa instradare domini scelti verso resolver scelti, che è il meccanismo che quei blocchi con scope espongono.

Il controllo che risolve la questione è se il resolver si trovi sul percorso che il tunnel ha installato:

scutil --nwi
ifconfig utun4
route -n get 10.20.0.53
netstat -rn | grep -m5 utun

Se route -n get restituisce un gateway e un’interfaccia che non corrispondono alla voce del resolver, l’indirizzo può essere perfettamente corretto e comunque irraggiungibile. Un tunnel diviso che porta solo le sottoreti aziendali scarta le query dirette a un server DNS fuori da esse, e il guasto si manifesta come timeout, per questo l’output di configurazione continua a sembrare pulito.

Interroga il resolver di sistema, poi il server

Tre strumenti rispondono a tre domande diverse, e confonderli produce la maggior parte delle conclusioni sbagliate in questo campo. dscacheutil -q host -a name passa per lo stesso resolver di sistema usato dalle applicazioni comuni, quindi si applicano i blocchi con scope e supplementari. dig senza argomento server legge /etc/resolv.conf, che non è la fonte di verità per la risoluzione con scope su macOS, e salta del tutto le regole per dominio. dig @address raggiunge esattamente un server e non dice nulla sulla selezione.

dscacheutil -q host -a name intranet.corp.example
dig intranet.corp.example
dig @10.20.0.53 intranet.corp.example
nslookup intranet.corp.example

Quando il primo comando risponde e il secondo restituisce NXDOMAIN, hai trovato la separazione che cercavi e nulla è rotto. Quando il primo va in timeout mentre dig @10.20.0.53 risponde, il resolver funziona ma non è raggiungibile sul percorso scelto dal tunnel, quindi il passo successivo è route -n get e non una modifica alle impostazioni DNS. Tieni i nomi privati fuori da tutto ciò che incolli in un ticket o in una nota condivisa.

Cosa l’output non può mostrarti

Diversi strati stanno sopra o accanto alla lista dei resolver, e ciascuno può inviare una query in un punto che l’output non menziona mai. Un browser con DNS sicuro attivo può risolvere sul proprio canale cifrato, quindi una pagina che carica mentre dscacheutil va in timeout non è una contraddizione. Un proxy DNS installato da un software di sicurezza gira come provider Network Extension e inoltra le query da sé, e scutil --dns mostra cosa è stato configurato, non l’indirizzo a monte che il proxy ha finito per usare. I domini di ricerca aggiungono una terza piega: a un nome non qualificato viene aggiunto ogni suffisso elencato in ordine, quindi il blocco che ha risposto può essere uno che non hai mai sospettato.

Le risposte stantie sono la cosa più economica da escludere e la più spesso saltata:

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
scutil --dns | head -20

Se l’output cambia dopo lo svuotamento, lo stato era in cache e l’output precedente descriveva un tunnel che non esisteva più. Se non cambia, la configurazione è quella che è, e la domanda si sposta sulle rotte e sulla politica delle applicazioni.

Un breve runbook per prima e dopo

Cattura una linea di base solo dove la politica lo consente, e tieni i file fuori da qualsiasi cartella sincronizzata. La sequenza qui sotto è quella che eseguo sulle macchine dei clienti: cattura la linea di base, connetti, cattura di nuovo, poi confronta e cerca.

scutil --dns > ~/dns-before.txt
# connect the VPN, then:
scutil --dns > ~/dns-after.txt
diff -u ~/dns-before.txt ~/dns-after.txt
dscacheutil -q host -a name intranet.corp.example

Leggi la differenza per blocchi invece che per righe. Un nuovo resolver con scope che porta l’indice dell’interfaccia del tunnel e una voce domain per il suffisso privato è la forma attesa. Un nuovo resolver predefinito che punta a un indirizzo pubblico è un riscontro che vale la pena sollevare con chi possiede il profilo del client. Poi ripeti la ricerca dentro l’applicazione che ha davvero fallito, non solo nella shell, e annota l’interfaccia da route -n get accanto al risultato.

Per annullare una modifica, disconnetti e ripeti la cattura della linea di base. Se il blocco con scope è sparito, il client ha ripulito da solo. Se il blocco è ancora elencato contro un’interfaccia che non esiste più, lo stato è stantio, e uno svuotamento più una riconnessione è la correzione più delicata prima che qualcuno tocchi il profilo.

Quattro controlli, in questo ordine: un blocco di resolver corrisponde al suffisso più lungo del nome; quel blocco è legato all’interfaccia che il tunnel ha installato; la rotta verso il suo server dei nomi passa per il tunnel; e il resolver di sistema, e non dig, restituisce la risposta. Il primo controllo che fallisce ti dice se cambiare la politica DNS, le rotte del tunnel o l’applicazione. Se tutti e quattro passano e il nome fallisce ancora, il problema sta sopra il DNS, e la prossima cosa da ispezionare è tutto ciò che risponde alla porta 53 davanti ad esso.

Articoli correlati