Perché le query di dnsmasq escono dalla VPN dopo un reindirizzamento DNS
Una REDIRECT lato router trasforma una query DNS della LAN in un nuovo socket del resolver. I marcatori sul flusso del client non arrivano mai fin lì, quindi imposta l’uscita verso l’upstream direttamente.
Il client della LAN raggiunge correttamente la sua VPN e, ciò nonostante, le sue query DNS compaiono sul collegamento ascendente sbagliato. Non è una fuga nel senso abituale; è quello che accade quando il router smette di inoltrare una query e risponde da sé. L’intercettazione riscrive la destinazione verso un socket locale, e poi il resolver apre una seconda conversazione, non correlata, con il proprio indirizzo di origine e la propria decisione di instradamento. I marcatori applicati al flusso del client descrivono la prima conversazione e assolutamente nulla della seconda.
Il marcatore non viaggia con la query
I marcatori di pacchetto vivono su una voce conntrack e sul pacchetto in volo. Una regola REDIRECT termina quel volo: il carico utile viene consegnato a un socket locale, e la voce originale ha fatto il suo lavoro. Ciò che lascia il router dopo è un socket nuovo creato dal processo del resolver, con l’indirizzo del router stesso come origine.
Per questo una rotta di policy imperniata sull’indirizzo del client della LAN non corrisponde mai alla query upstream. Il nuovo socket appartiene a dnsmasq e non al client, e il kernel valuta la rotta per il traffico del router stesso. Le regole di origine, le regole di interfaccia e le regole di marcatura vedono tutte una tupla diversa. Presumere che il marcatore si propaghi è l’errore più comune in questa configurazione, ed è invisibile in una cattura lato client.
Le due conversazioni condividono davvero un nome e una temporizzazione, ed è questo che le fa sembrare un solo flusso quando si scorre rapidamente una cattura.
Dove l’inoltro diventa risoluzione locale
Inizia stabilendo se la porta 53 è reindirizzata, tradotta verso un altro host o lasciata intatta, perché i tre casi si comportano diversamente. Un reindirizzamento verso una porta locale termina l’inoltro, mentre una traduzione verso un’altra macchina tiene il pacchetto in movimento e mantiene significativa la tupla del client.
Guarda entrambi i protocolli. Un resolver raggiungibile su UDP e TCP sarà testato su entrambi, e un insieme di regole che copre solo UDP lascia un buco silenzioso per le risposte grandi. Anche le regole generate dal gestore di configurazione del router contano, e modificare un file generato di solito perde contro il successivo ricaricamento.
sudo nft list ruleset | grep -n -B2 -A4 'dport 53'
sudo iptables -t nat -L -n -v | grep -E ':53|dns'
sudo ss -lunp | grep ':53'
Questi output rispondono a tre domande in ordine: che cosa riscrive la query, che cosa la riceve e quale processo possiede il socket in ascolto. Una volta noto il proprietario, la policy upstream ha dove vivere.
Dai al resolver una policy di uscita propria
Un upstream specifico per dominio è lo strumento più pulito quando solo alcuni nomi hanno bisogno del tunnel. dnsmasq accetta una riga server limitata a un dominio, con un’interfaccia o un indirizzo di origine opzionale che dirige la query fuori da un dispositivo scelto. È quel direzionamento che fa seguire la VPN alla seconda conversazione.
server=/corp.example/10.30.0.53@tun_work
log-queries
Il dominio, l’indirizzo e l’interfaccia qui sopra sono segnaposto per i tuoi valori. La selezione del dominio e il controllo dell’uscita restano decisioni separate: la rotta deve esistere, l’indirizzo di origine deve essere consentito dal resolver upstream e il firewall deve consentire la risposta. Il direzionamento per sola interfaccia non è fail-closed, perché un tunnel svanito può lasciare il resolver a ricadere su un altro percorso. Tieni qualsiasi ripiego pubblico lontano da uno spazio di nomi che deve restare privato.
Metti la riga presso il proprietario di configurazione che il router supporta, non in un file generato, altrimenti il ricaricamento successivo cancella la correzione.
Che cosa una cache condivisa non può preservare
Un solo forwarder con una sola cache serve ogni client della LAN, e questo fa crollare una distinzione di cui alcune reti hanno bisogno. Se due client devono risolvere lo stesso nome in modo diverso, il socket condiviso non ha modo di recuperare quale client abbia chiesto. La policy per client deve vivere in istanze del resolver separate o in una funzione di inoltro che conserva l’identità.
Una risposta in cache non è nemmeno una prova sul nuovo percorso. La risposta può arrivare dalla memoria mentre la rotta upstream resta rotta.
Le regole sulla porta 53 non dicono nulla sulle applicazioni che parlano DNS su HTTPS o su TLS. Quelle query non raggiungono mai il reindirizzamento, quindi una policy costruita solo sulla porta 53 descrive un sottoinsieme del traffico e dovrebbe essere documentata come sottoinsieme.
Verifica la seconda conversazione, non la prima
Prova con un nome che controlli e osserva entrambi i lati. Una cattura lato client dimostra che la query ha lasciato la LAN; solo il lato router dimostra dove è andata dopo.
sudo tcpdump -ni tun_work udp port 53
ip route get 10.30.0.53
dig +short corp.example @10.30.0.53
Svuota la cache prima di ogni tentativo, perché una risposta calda nasconde un upstream rotto. Ripeti su TCP, poi ripeti con il tunnel abbassato per vedere che cosa fa il resolver quando il suo percorso preferito non c’è più. È quest’ultimo comportamento a decidere se il progetto è fail-closed o solo fortunato.