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

Два способа переключить выход

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

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

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

Дайте каждому выходу свою таблицу

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

ip rule add fwmark 0x10/0x10 table 101
ip rule add fwmark 0x20/0x20 table 102
ip route add default via 192.0.2.1 dev wg-a table 101
ip route add default via 198.51.100.1 dev wg-b table 102

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

Выберите один раз, на первом пакете

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

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

nftables держит метки пакета и соединения отдельно, а руководство по метаинформации документирует явное копирование между ними. Метка соединения сама не становится меткой пакета, с которой совпадает ваше правило, и это самая частая причина, по которой аккуратно написанный классификатор не даёт эффекта.

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

Четыре фазы дренажа

  1. Подготовьте B, не трогая A: маршрутизация, пересылка, авторизация, NAT и обратный путь. Установите его таблицу и политику выбора через существующего владельца конфигурации шлюза.

  2. Переключите классификатор так, чтобы новые, неклассифицированные соединения выбирали B, сохраняя сохранённые выборы. Атомарная транзакция nftables избегает окна, в котором нужно очищать старое состояние.

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

  4. Выведите A из эксплуатации, когда условие дренажа выполнено, судя по состоянию соединений и поведению приложения, а не по одному тихому интервалу.

Чего дренаж не может обещать

Запрос браузера — это не новое транспортное соединение; объединение продолжает отправлять запросы по старому. Наоборот, поток UDP может устареть из conntrack, и более поздний пакет классифицируется заново. Дренаж следует за отслеживаемыми потоками, а не за представлением приложения о сеансе.

Если A откажет до завершения его потоков, сохранённая метка их не спасёт. Они переподключаются через B или не переподключаются вовсе. Плановый дренаж покупает непрерывность, пока исходный путь здоров; это не репликация состояния между независимыми выходами.

Проверьте обе половины

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

Не очищайте таблицу conntrack, чтобы новый выбор появился. Это уничтожает именно то состояние, которое дренаж должен сохранить, и превращает контролируемую миграцию в сбой с чисто выглядящим тестом.

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