Fermate due servizi Linux che si contendono /etc/resolv.conf
Scoprite chi possiede il file prima di modificarlo. L'attributo immutable nasconde il conflitto, e le riconnessioni o i rinnovi DHCP annullano ripetutamente una riparazione DNS manuale.
Il DNS continua a tornare allo stato precedente, la riconnessione VPN annulla la vostra correzione e alla fine qualcuno del team propone di bloccare il file. Questa sequenza è un sintomo, non una soluzione: due componenti credono entrambi di possedere /etc/resolv.conf, e vince l'ultimo che scrive. Bloccare il file non risolve il conflitto di proprietà, lo nasconde soltanto e intanto rompe il componente che volevate davvero. Eseguite le quattro verifiche seguenti in ordine e correggete la disposizione al livello che la possiede, non al file.
Verifica 1: è un collegamento simbolico, e verso cosa
Partite dal file stesso, perché il percorso che state modificando potrebbe non essere affatto il file. Un collegamento simbolico alla directory di runtime di un resolver si comporta in modo del tutto diverso da un file normale che uno script client riscrive:
ls -l /etc/resolv.conf
readlink -f /etc/resolv.conf
cat /etc/resolv.conf
Un collegamento a un percorso stub di systemd-resolved significa che il contenuto del file viene generato, e la modifica manuale verrà sovrascritta al prossimo evento. Un file normale con righe nameserver viene di solito scritto dal client o dall'hook DHCP che viene eseguito alla connessione. Entrambi sono legittimi; ciò che conta è sapere quale avete prima di cambiare qualcosa.
Verifica 2: quale demone è in esecuzione
Scoprite cosa è realmente attivo, non cosa è installato. Su una distribuzione moderna possono essere presenti più resolver, e quello che occupa la porta 53 sull'interfaccia loopback è quello che risponde:
systemctl status systemd-resolved --no-pager
resolvectl status
ss -lunp | grep ':53'
L'output di stato elenca i server DNS per collegamento e i domini di routing, cioè la mappa che vi serve per il DNS diviso. Se i nomi interni devono andare a un server interno e tutto il resto a uno pubblico, quella politica vive nei domini per collegamento, e appiattirla in un elenco statico di nameserver nel file fa perdere silenziosamente quella distinzione.
La configurazione di NetworkManager stesso decide quale di questi backend usa. La sua impostazione dns= nel file di configurazione principale sceglie tra il suo resolver interno, dnsmasq, systemd-resolved e none, e la distribuzione potrebbe aver scelto per voi. Leggete quell'impostazione prima di decidere cosa significa “riparare il DNS” su questo host.
Verifica 3: cosa può scrivere il client VPN
È qui che di solito vive il conflitto. Un client VPN che riscrive direttamente il file del resolver si scontrerà con qualsiasi servizio che lo mantiene anch'esso, e il perdente è chi viene eseguito per primo. Le versioni recenti di OpenVPN possono consegnare le impostazioni DNS a systemd-resolved invece di riscrivere il file, che è il comportamento collaborativo che volete; gli script più vecchi e gli hook scritti a mano spesso chiamano un helper obsoleto o semplicemente sovrascrivono il file.
La situazione di WireGuard è simile nella forma: la configurazione dell'interfaccia non gestisce il DNS, lo fanno gli strumenti attorno ad essa, tramite un helper del resolver o l'integrazione con resolved. Se sono installati due di questi helper, entrambi cercheranno di applicare la propria visione del mondo alla connessione.
Leggete gli hook di attivazione e disattivazione del client invece di indovinare. Poche righe di shell in /etc/openvpn/up.sh o in una directory equivalente spiegano un comportamento che altrimenti sembra casuale, ed è anche il punto in cui potete far collaborare il client invece di farlo competere.
Verifica 4: correggete dal proprietario, non nel file
Una volta noto il proprietario, configurate il DNS tramite l'interfaccia supportata da quel proprietario. Per systemd-resolved significa impostazioni per collegamento e domini di routing invece di un file statico; per NetworkManager significa le impostazioni DNS del profilo di connessione e il backend scelto; per una distribuzione con integrazione resolvconf significa scrivere tramite quell'helper.
Non rendete il file immutabile. L'attributo immutable arresta i rinnovi DHCP legittimi e gli aggiornamenti VPN insieme a quelli che combattevate, e lascia il sistema in uno stato in cui il prossimo aggiornamento dei pacchetti o la riconnessione produce un guasto che nessuno può spiegare dalla configurazione. Nasconde il conflitto di proprietà, che è proprio ciò che cercavate di risolvere.
Dove due componenti devono davvero coesistere, date loro compiti diversi. Lasciate che il gestore di rete possieda la configurazione a livello di interfaccia, lasciate che il client VPN apporti DNS e domini per collegamento tramite la stessa integrazione, e rimuovete il terzo script che scrive il file direttamente. La documentazione di systemd-resolved espone le modalità supportate e ciò che ciascuna espone in /etc/resolv.conf. Scegliete la modalità che corrisponde alla quantità di politica da conservare. Se il DNS diviso conta, la disposizione stub con domini per collegamento lo preserva, mentre la modalità che copia i server upstream nel file lo appiattisce silenziosamente.
Verificate dopo una riconnessione, non dopo la modifica
Un file che sembra corretto subito dopo la vostra modifica non dimostra nulla, perché l'evento successivo non è ancora avvenuto. Attivate la sequenza che prima lo rompeva: abbassate e rialzate il tunnel, rinnovate il lease DHCP o cambiate l'interfaccia, poi rileggete gli stessi valori.
resolvectl query build.corp.example
resolvectl query example.com
resolvectl status | head -40
Poi confermate la distinzione che conta: il nome interno si risolve tramite il server interno mentre il nome pubblico funziona ancora. Una configurazione che manda tutto al server interno sembra a posto finché qualcuno non prova a raggiungere internet attraverso il tunnel, e una configurazione che manda tutto a quello pubblico fa trapelare i nomi interni.
Annotate il proprietario, il backend e la modalità del collegamento simbolico nelle note di distribuzione. Quel singolo paragrafo trasforma un futuro aggiornamento dei pacchetti da incidente in voce di revisione, e impedisce alla persona successiva di riscoprire lo stesso conflitto con un comando chattr.