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

Поиск происходит раньше, чем источник перезаписывается

Для пакета, пересылаемого от клиента VPN, ядро выполняет фиксированную последовательность. Он приходит на интерфейс туннеля, проходит prerouting, где живут conntrack и DNAT, затем принимается решение о маршрутизации, затем пересылка, затем postrouting, где SNAT применяется последним. Правило вида from рассматривается во время этого решения о маршрутизации, то есть видит исходный адрес клиента, а не транслированный.

Поэтому добавление правила masquerade не меняет того, какая политика соответствует исходящему потоку. Меняется то, что видит дальняя сторона, а значит, какой обратный путь существует. Это два разных следствия, и обзоры изменений постоянно их путают. Разделите их, и проект обычно становится очевидным в течение минуты.

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

StageSource the kernel seesWhat it means for your rule
PreroutingClient address, 172.31.7.42Where marks and DNAT are applied
Routing decisionStill 172.31.7.42This is where from rules match
PostroutingBecomes 198.51.100.9What the far end and its return route see

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

Тест со шлюза — не тест пула

Трафик, который порождает сам шлюз, никогда не проходит через prerouting, потому что он не пришёл ни на какой интерфейс. Он маршрутизируется в выходном пути, с адресом самого шлюза в качестве источника, и правило from, привязанное к диапазону клиентов, не совпадёт. Каждый тикет в этой области, говорящий, что с коробки работает, а с клиента нет, — это повторение того же факта.

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

ip route get 198.51.100.9 from 172.31.7.42 iif tun0
ip route get 198.51.100.9 from 172.31.8.42 iif tun0
ip route show table 201

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

Приоритет, а не место в файле

Правила оцениваются в порядке возрастания приоритета, и значение имеет число, а не порядок, в котором вы их набрали. Таблица local находится на приоритете 0, таблица main — на 32766, а правило по умолчанию — на 32767, поэтому правило, добавленное с приоритетом по умолчанию, оказывается ближе к концу списка и проигрывает почти всему.

ip rule show
ip rule add from 172.31.8.0/24 lookup 201 priority 1000
ip -4 route show table 201

Явный приоритет делает предполагаемый порядок видимым в файле и при обзоре. Он также не позволяет более позднему дополнению молча обогнать существующее правило, что является самой частой причиной того, что работающая политика перестаёт работать после несвязанного изменения.

Совпадающее правило, указывающее на неполную таблицу, — другая ловушка. Если в таблице 201 есть маршрут по умолчанию, но нет маршрута к назначению, пакет отбрасывается или отправляется не туда, а правило в изоляции выглядит совершенно правильным. Читайте таблицу, а не только правило. Правило — это указатель, а пустая таблица — указатель в никуда.

Обратный путь всё равно должен существовать

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

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

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

Не ловите собственный туннель шлюза в политике

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

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

Страница руководства ip-rule описывает семантику селектора и приоритета. Соедините её с тестом поиска для каждого пула, и проект станет проверяемым, в чём и состоит разница между политической маршрутизацией, которая держится год, и той, которую все боятся трогать.

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