Вы добавляете одну строку, чтобы сохранить локальный маршрут по умолчанию, и после этого туннель больше не достигает внутреннего 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 textWhat it actually matchesTypical outcome
"route"Every option beginning with those lettersRoutes, gateway, metric and IPv6 routes all dropped
"route "Route entries only, not the hyphenated siblingsThe routes go, the rest survives
"route 10.60."A single destination rangeThe narrowest rule, and the easiest to audit
"dhcp-option DNS"Pushed DNS settingsResolver stays local, internal names stop resolving

Последняя строка — та, что ловит людей при работе с разделённым туннелем. Держать собственный резолвер — законный выбор, и это означает, что каждое внутреннее имя теперь зависит от резолвера, который не видит частную зону. Это следствие, которое принимают осознанно, а не побочный эффект, который обнаруживают в продакшене.

Сопоставление по префиксу означает и то, что правило может позже тихо расшириться. Когда сервер добавляет новую опцию, начинающуюся с вашего текста, ваш фильтр начинает применяться и к ней, хотя никто не редактировал профиль. Это и есть режим отказа, против которого нужно проектировать, а смягчение — совпадать с как можно большей частью опции, а не с как можно меньшей.

Три глагола с тремя разными результатами

accept, ignore и reject — не три написания одной идеи. Они различаются тем, что клиент делает с совпадением, и тем, узнает ли об этом кто-нибудь.

ignore тихо отбрасывает совпавшую опцию, что нужно для настройки, которую вы осознанно заменили. reject отбрасывает её и заставляет клиент жаловаться, что нужно, когда её отсутствие должно быть видно в журнале, а не обнаружено позже. accept — положительная форма, применяется, когда вы строите список разрешённых, а не удаляете отдельные опции.

Какой бы глагол вы ни использовали, фильтры применяются в порядке появления, поэтому два перекрывающихся правила дают зависящий от порядка результат, который очень трудно проверять. Держите одно правило на одну цель и помещайте в каждое самый конкретный текст. Если нужен список разрешённых, предпочтите несколько правил accept груде правил ignore, которые дают то же самое. Тогда проверяющие могут прочитать файл сверху вниз и предсказать результат, и это единственный тест, который масштабируется.

Проверяйте применённый маршрут и резолвер, а не профиль

Фильтр, который выглядит правильным в файле, всё ещё может оставить вас с туннелем, который не маршрутизирует ничего полезного. Проверьте эффект в работающей системе, где проталкиваемые опции уже применены или отброшены:

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/

Первые две строки говорят вам, пришёл ли проталкиваемый маршрут по умолчанию и сколько статических записей уцелело. Запрос к резолверу показывает, какой сервер на самом деле использует интерфейс туннеля, и обычно именно там появляется сюрприз с DNS. Последняя строка отвечает на единственный вопрос, важный для пользователя.

Проверьте оба направления, пока вы там. Правило, которое сохраняет ваш локальный интернет рабочим, но тихо ломает внутреннее разрешение имён, проходит поверхностную проверку и проваливается на первой настоящей задаче, поэтому включите в тот же тест один внутренний ресурс и один публичный сайт.

Запишите исключение и его владельца

Фильтр — это исключение из замысла оператора, поэтому запишите его с причиной и точкой проверки. «Игнорирует проталкиваемые маршруты, чтобы сохранить локальный по умолчанию» поддаётся проверке; голая строка в профиле — нет, и следующий человек удалит её или расширит наугад.

Версия здесь тоже важна. Поведение сопоставления и точный принимаемый синтаксис совершенствовались в OpenVPN 2.4, 2.5 и 2.6, поэтому подтверждайте шаблон по руководству той сборки, которую вы поставляете, а не по сообщению на форуме о старой версии. Руководство OpenVPN 2.6 документирует эту опцию и её правило сопоставления.

Наконец, согласуйте исключение с тем, кто управляет сервером. Клиентский фильтр, противоречащий намеренной политике сервера, — это инцидент поддержки, ждущий следующего аудита, и гораздо дешевле уладить его до отправки профиля, чем после того, как кто-то заметит отсутствие маршрутов.

Похожие статьи