pull-filter в OpenVPN съвпада с повече от маршрута, който имахте предвид
pull-filter сравнява текста ви като префикс с изпратените опции, затова route прихваща също route-gateway и route-ipv6. Проверете глаголите, после маршрутите.
Добавяте един ред, за да запазите локалния си маршрут по подразбиране, и след това тунелът вече не достига до вътрешния DNS сървър. Редът беше pull-filter ignore "route", което не означава "игнорирай този маршрут". Означава "изхвърли всяка изпратена опция, чийто текст започва с тези пет букви", а на нормален сървър това включва route-gateway, route-metric и route-ipv6 заедно със самите маршрути. Списъкът за проверка по-долу е това, което изпълнявам, преди да пипна профил, който някой друг трябва да използва.
Филтърът действа само върху изпратени опции
pull-filter действа върху редовете с опции, които сървърът изпраща след установяване на тунела, и върху нищо друго. Опциите, записани в локалния ви файл, не се засягат от него, както и трафикът на приложенията. Ако сте се надявали да спрете процес да използва тунела, това е напълно грешният инструмент и никаква комбинация от филтри няма да го постигне.
Този обхват е полезен, защото означава, че можете да оставите конфигурацията на сървъра непокътната и въпреки това да откажете част от нея локално. Това е и ограничение, което си струва да се запише в тикета: филтърът променя какво приема този клиент, а не какво предлага сървърът. Той не влияе на други потребители на същия профил. Не оцелява и при преминаване към друг клиент, който не реализира опцията, което си струва да се знае, преди да изградите работен процес върху нея.
Потвърдете какво всъщност изпраща сървърът, преди да напишете шаблона. При висока степен на подробност клиентът отпечатва получения низ с изпратени опции и това е единственият честен източник за точния текст, с който сравнявате:
sudo openvpn --config /etc/openvpn/corp.ovpn --verb 4
sudo grep -n 'pull-filter' /etc/openvpn/corp.ovpn
Четете изпратения ред като списък от опции, разделени със запетаи, и отбележете, че имената на опциите и аргументите им са разделени с интервали. Текстът на филтъра ви се сравнява с този поток, затова интервалите са толкова важни в следващата стъпка.
Съвпадението е префикс, затова интервалите решават всичко
Сравнението е префикс на низ, а не анализирано име на опция. Затова "route" съвпада с route-gateway 10.8.0.1, route-ipv6 2001:db8::/32 и route-metric 100. Един интервал в края го стеснява до семейството, което вероятно имате предвид, а пълният префикс го стеснява допълнително до конкретна дестинация.
| 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 |
Последният ред е този, който хваща хората при работа с разделен тунел. Да запазите свой resolver е законен избор и означава, че всяко вътрешно име вече зависи от resolver, който не вижда частната зона. Това е последица, която се приема нарочно, а не страничен ефект, който се открива в продукция.
Съвпадението по префикс означава също, че правилото може по-късно да се разшири тихо. Когато сървърът добави нова опция, започваща с вашия текст, филтърът ви започва да се прилага към нея, без някой да редактира профила ви. Това е режимът на отказ, срещу който трябва да се проектира, и смекчаването е да съвпадате с възможно най-голямата част от опцията, а не с възможно най-малката.
Три глагола с три различни последици
accept, ignore и reject не са три изписвания на една и съща идея. Те се различават по това какво прави клиентът при съвпадение и по това дали някой ще разбере.
ignore изхвърля съвпадащата опция тихо, което е желаното за настройка, която сте заменили умишлено. reject я изхвърля и кара клиента да се оплаче, което е желаното, когато отсъствието ѝ трябва да се вижда в журнала, а не да се открие по-късно. accept е положителната форма, използва се, когато изграждате списък за разрешаване, а не когато премахвате отделни опции.
Който и глагол да използвате, филтрите се прилагат в реда, в който се появяват, така че две припокриващи се правила дават резултат, зависим от реда, и много труден за преглед. Дръжте едно правило на намерение и слагайте най-конкретния текст във всяко. Ако ви трябва списък за разрешаване, предпочитайте малък брой правила accept пред куп правила ignore, които дават същото. Тогава рецензентите могат да прочетат файла отгоре до долу и да предскажат резултата, а това е единственият тест, който се мащабира.
Проверете приложения маршрут и resolver, не профила
Филтър, който изглежда правилен във файла, все още може да ви остави с тунел, който не маршрутизира нищо полезно. Проверете ефекта в работещата система, където изпратените опции вече са приложени или изхвърлени:
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/
Първите два реда ви казват дали изпратеният маршрут по подразбиране е пристигнал и колко статични записа са оцелели. Заявката към resolver показва кой сървър всъщност използва интерфейсът на тунела и обикновено там се появява изненада с DNS. Последният ред отговаря на единствения въпрос, който има значение за потребителя.
Тествайте и двете посоки, докато сте там. Правило, което запазва локалния ви интернет работещ, но тихо чупи вътрешното разрешаване на имена, минава повърхностна проверка и се проваля при първата реална задача, затова включете един вътрешен ресурс и един публичен сайт в същия тест.
Запишете изключението и кой го притежава
Филтърът е изключение от замисъла на оператора, затова го запишете с причина и точка за преглед. "Игнорира изпратени маршрути, за да запази локалния по подразбиране" е прегледимо; гол ред в профил не е и следващият човек ще го изтрие или разшири с догадки.
Версията има значение и тук. Поведението при съвпадение и точният приет синтаксис са усъвършенствани в OpenVPN 2.4, 2.5 и 2.6, затова потвърдете шаблона по ръководството за изданието, което доставяте, а не по форумен пост за по-стара версия. Ръководството на OpenVPN 2.6 документира опцията и нейното правило за съвпадение.
Накрая, съгласувайте изключението с този, който управлява сървъра. Клиентски филтър, който противоречи на умишлена сървърна политика, е инцидент за поддръжка, който чака следващия одит, и е много по-евтино да се уреди преди профилът да бъде изпратен, отколкото след като някой забележи, че маршрутите липсват.