OpenVPN pull-filter matchar mer än rutten du menade
pull-filter jämför din text som ett prefix mot pushade alternativ, så route fångar även route-gateway och route-ipv6. Kontrollera verben, sedan rutterna.
Du lägger till en rad för att behålla din lokala standardrutt, och efter det når tunneln inte längre den interna DNS-servern. Raden var pull-filter ignore "route", vilket inte betyder "ignorera den här rutten". Det betyder "släpp varje pushat alternativ vars text börjar med de fem bokstäverna", och på en vanlig server omfattar det route-gateway, route-metric och route-ipv6 tillsammans med själva rutterna. Checklistan nedan är vad jag går igenom innan jag rör en profil som någon annan måste använda.
Filtret gäller bara pushade alternativ
pull-filter verkar bara på de alternativrader som servern skickar efter att tunneln är upprättad, och på ingenting annat. Alternativ som skrivits i din lokala fil påverkas inte av det, och applikationstrafik inte heller. Om du hoppades hindra en process från att använda tunneln är detta helt fel verktyg och ingen kombination av filter kommer att göra det.
Den omfattningen är användbar, eftersom den innebär att du kan lämna serverns konfiguration i fred och ändå avvisa en del av den lokalt. Det är också en begränsning som är värd att notera i ärendet: ett filter ändrar vad den här klienten accepterar, inte vad servern erbjuder. Det har ingen effekt på andra användare av samma profil. Det överlever inte heller ett byte till en annan klient som inte implementerar alternativet, vilket är värt att veta innan du bygger ett arbetsflöde på det.
Bekräfta vad servern faktiskt skickar innan du skriver mönstret. Vid hög detaljrikedom skriver klienten ut den pushade alternativsträngen den tog emot, och det är den enda ärliga källan till den exakta text du matchar mot:
sudo openvpn --config /etc/openvpn/corp.ovpn --verb 4
sudo grep -n 'pull-filter' /etc/openvpn/corp.ovpn
Läs den pushade raden som en lista med alternativ åtskilda av kommatecken, och notera att alternativnamn och deras argument åtskils av mellanslag. Din filtertext jämförs med den strömmen, därför spelar mellanslag så stor roll i nästa steg.
Matchningen är ett prefix, så mellanslagen avgör allt
Jämförelsen är ett strängprefix, inte ett tolkat alternativnamn. Därför matchar "route" både route-gateway 10.8.0.1, route-ipv6 2001:db8::/32 och route-metric 100. Ett mellanslag i slutet snävar in det till familjen du förmodligen menade, och det fullständiga prefixet snävar in det ytterligare till en bestämd destination.
| 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 |
Den sista raden är den som fångar folk under arbete med delad tunnel. Att behålla sin egen resolver är ett legitimt val, och det innebär att varje internt namn nu beror på en resolver som inte kan se den privata zonen. Det är en konsekvens man accepterar med avsikt, inte en bieffekt man upptäcker i produktion.
Prefixmatchning innebär också att en regel senare kan vidgas tyst. När servern lägger till ett nytt alternativ som börjar med din text börjar ditt filter gälla för det utan att någon redigerar din profil. Det är det felläge man måste designa mot, och mildringen är att matcha så mycket av alternativet som möjligt i stället för så lite som möjligt.
Tre verb med tre olika utfall
accept, ignore och reject är inte tre stavningar av samma idé. De skiljer sig i vad klienten gör med en matchning och i om någon får reda på det.
ignore släpper den matchande inställningen tyst, vilket du vill ha för en inställning du medvetet har ersatt. reject släpper den och får klienten att klaga, vilket du vill ha när dess frånvaro ska synas i en logg i stället för att upptäckas senare. accept är den positiva formen, används när du bygger en tillåtelselista i stället för att ta bort enskilda alternativ.
Vilket verb du än använder tillämpas filtren i den ordning de förekommer, så två överlappande regler ger ett ordningsberoende resultat som är mycket svårt att granska. Håll en regel per avsikt och sätt den mest specifika texten i varje. Om du behöver en tillåtelselista, föredra några få accept-regler framför en hög med ignore-regler som summerar till samma sak. Då kan granskare läsa filen uppifrån och ned och förutse resultatet, och det är det enda testet som skalar.
Kontrollera den tillämpade rutten och resolvern, inte profilen
Ett filter som ser korrekt ut i filen kan ändå lämna dig med en tunnel som inte dirigerar något användbart. Verifiera effekten på det körande systemet, där pushade alternativ redan har tillämpats eller släppts:
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/
De två första raderna berättar om den pushade standardrutten kom fram och hur många statiska poster som överlevde. Resolver-frågan visar vilken server tunnelgränssnittet faktiskt använder, och det är oftast där en DNS-överraskning dyker upp. Den sista raden besvarar den enda fråga som betyder något för en användare.
Testa båda riktningarna medan du är där. En regel som håller ditt lokala internet igång men tyst bryter den interna namnmatchningen klarar en ytlig kontroll och misslyckas vid den första riktiga uppgiften, så ta med en intern resurs och en offentlig webbplats i samma test.
Anteckna undantaget och vem som äger det
Ett filter är ett undantag från operatörens design, så skriv ned det med en anledning och en granskningspunkt. "Ignorerar pushade rutter för att behålla den lokala standarden" går att granska; en bar rad i en profil går inte, och nästa person kommer att radera den eller utöka den genom gissningar.
Versionen spelar roll här också. Matchningsbeteendet och den exakta accepterade syntaxen har finslipats genom OpenVPN 2.4, 2.5 och 2.6, så bekräfta mönstret mot manualen för den build du levererar och inte mot ett foruminlägg om en äldre version. OpenVPN 2.6-manualen dokumenterar alternativet och dess matchningsregel.
Till sist, kom överens om undantaget med den som driftar servern. Ett klientsidigt filter som motsäger en medveten serverpolicy är en supportincident som väntar på nästa revision, och det är mycket billigare att lösa den innan profilen skickas ut än efter att någon har märkt att rutterna saknas.