Il pull-filter di OpenVPN corrisponde a più della rotta che intendevi
pull-filter confronta il tuo testo come prefisso con le opzioni inviate, quindi route cattura anche route-gateway e route-ipv6. Controlla i verbi, poi le rotte.
Aggiungi una riga per mantenere la rotta predefinita locale, e dopo il tunnel non raggiunge più il server DNS interno. La riga era pull-filter ignore "route", che non significa "ignora questa rotta". Significa "scarta ogni opzione inviata il cui testo inizia con quelle cinque lettere", e su un server normale questo include route-gateway, route-metric e route-ipv6 insieme alle rotte stesse. La lista di controllo qui sotto è quella che percorro prima di toccare un profilo che qualcun altro deve usare.
Il filtro agisce solo sulle opzioni inviate
pull-filter agisce sulle righe di opzione che il server invia dopo l'istituzione del tunnel, e su nient'altro. Le opzioni scritte nel tuo file locale non ne sono influenzate, né lo è il traffico delle applicazioni. Se speravi di impedire a un processo di usare il tunnel, questo è completamente lo strumento sbagliato e nessuna combinazione di filtri lo farà.
Questa portata è utile, perché significa che puoi lasciare in pace la configurazione del server e comunque rifiutarne una parte localmente. È anche un limite che vale la pena annotare nel ticket: un filtro cambia ciò che questo client accetta, non ciò che il server offre. Non ha alcun effetto sugli altri utenti dello stesso profilo. Non sopravvive nemmeno a un passaggio a un altro client che non implementa l'opzione, cosa che vale la pena sapere prima di costruirci sopra un flusso di lavoro.
Conferma cosa invia realmente il server prima di scrivere il modello. Con verbosità alta il client stampa la stringa di opzioni inviate che ha ricevuto, e questa è l'unica fonte onesta per il testo esatto con cui confronti:
sudo openvpn --config /etc/openvpn/corp.ovpn --verb 4
sudo grep -n 'pull-filter' /etc/openvpn/corp.ovpn
Leggi la riga inviata come un elenco di opzioni separate da virgole, e nota che i nomi delle opzioni e i loro argomenti sono separati da spazi. Il tuo testo di filtro viene confrontato con quel flusso, per questo gli spazi contano così tanto nel passaggio successivo.
La corrispondenza è un prefisso, quindi gli spazi sono tutto
Il confronto è un prefisso di stringa, non un nome di opzione analizzato. Quindi "route" corrisponde a route-gateway 10.8.0.1, route-ipv6 2001:db8::/32 e route-metric 100. Uno spazio finale lo restringe alla famiglia che probabilmente intendevi, e il prefisso completo lo restringe ulteriormente a una destinazione specifica.
| Filter text | What it actually matches | Typical outcome |
|---|---|---|
"route" | Every option beginning with those letters | Routes, gateway, metric and IPv6 routes all dropped |
"route " | Route entries only, not the hyphenated siblings | The routes go, the rest survives |
"route 10.60." | A single destination range | The narrowest rule, and the easiest to audit |
"dhcp-option DNS" | Pushed DNS settings | Resolver stays local, internal names stop resolving |
L'ultima riga è quella che coglie le persone durante il lavoro con tunnel diviso. Conservare il proprio resolver è una scelta legittima, e significa che ogni nome interno ora dipende da un resolver che non può vedere la zona privata. È una conseguenza da accettare di proposito, non un effetto collaterale da scoprire in produzione.
La corrispondenza per prefisso significa anche che una regola può allargarsi in silenzio più avanti. Quando il server aggiunge un'opzione che inizia con il tuo testo, il tuo filtro inizia ad applicarsi anche a quella senza che nessuno modifichi il profilo. È la modalità di guasto contro cui progettare, e la mitigazione è far corrispondere quanta più parte possibile dell'opzione, non quanta meno possibile.
Tre verbi con tre esiti diversi
accept, ignore e reject non sono tre grafie della stessa idea. Differiscono in ciò che il client fa con una corrispondenza e se qualcuno lo scopre.
ignore scarta silenziosamente l'opzione corrispondente, che è ciò che vuoi per un'impostazione che hai sostituito deliberatamente. reject la scarta e fa lamentare il client, che è ciò che vuoi quando la sua assenza deve essere visibile in un registro invece di essere scoperta più tardi. accept è la forma positiva, usata quando costruisci un elenco di autorizzati invece di rimuovere singole opzioni.
Qualunque verbo tu usi, i filtri vengono applicati nell'ordine in cui compaiono, quindi due regole sovrapposte producono un risultato dipendente dall'ordine e molto difficile da rivedere. Tieni una regola per intento e metti il testo più specifico in ciascuna. Se ti serve un elenco di autorizzati, preferisci poche regole accept a una pila di regole ignore che si sommano allo stesso. Allora i revisori possono leggere il file dall'alto in basso e prevedere il risultato, e questo è l'unico test che scala.
Verifica la rotta e il resolver applicati, non il profilo
Un filtro che sembra corretto nel file può comunque lasciarti con un tunnel che non instrada nulla di utile. Verifica l'effetto sul sistema in esecuzione, dove le opzioni inviate sono già state applicate o scartate:
ip route show default
ip route show | grep -c 'proto static'
resolvectl status | grep -A4 'Link.*tun0'
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://intranet.example.internal/
Le prime due righe ti dicono se la rotta predefinita inviata è arrivata e quante voci statiche sono sopravvissute. L'interrogazione al resolver mostra quale server usa davvero l'interfaccia del tunnel, ed è di solito lì che appare una sorpresa DNS. L'ultima riga risponde all'unica domanda che conta per un utente.
Prova entrambe le direzioni mentre sei lì. Una regola che tiene in funzione il tuo internet locale ma rompe in silenzio la risoluzione dei nomi interni passa un controllo superficiale e fallisce al primo compito reale, quindi includi una risorsa interna e un sito pubblico nella stessa prova.
Registra l'eccezione e chi ne è responsabile
Un filtro è un'eccezione al progetto dell'operatore, quindi scrivilo con un motivo e un punto di revisione. "Ignora le rotte inviate per conservare la predefinita locale" è rivedibile; una riga nuda in un profilo no, e la persona successiva la cancellerà o la amplierà a caso.
Anche la versione conta qui. Il comportamento di corrispondenza e la sintassi accettata esatta sono stati affinati in OpenVPN 2.4, 2.5 e 2.6, quindi conferma il modello sul manuale della build che distribuisci e non su un post di forum su una versione più vecchia. Il manuale di OpenVPN 2.6 documenta l'opzione e la sua regola di corrispondenza.
Infine, concorda l'eccezione con chi gestisce il server. Un filtro lato client che contraddice una politica deliberata del server è un incidente di supporto in attesa del prossimo audit, ed è molto più economico risolverlo prima che il profilo venga distribuito che dopo che qualcuno nota che mancano le rotte.