IP VPN-клиента в Kubernetes: сохранить или сделать SNAT?
Выберите между сохранением реального адреса VPN-клиента и NAT источника в Kubernetes по трём условиям, затем проверьте обратный путь и смену подов.
Где-то между туннелем и бэкендом адрес клиента либо выживает, либо заменяется, и оба исхода защитимы. Выбор принадлежит владельцу принимающего сервиса, а не тому, кто установил CNI. Когда важны авторизация по каждому клиенту, квоты или записи аудита, адрес должен выжить на каждом шаге. Когда общее приписывание приемлемо, NAT источника убирает проблему маршрутизации, которую иначе вы поддерживали бы вечно.
Где адрес клиента на самом деле исчезает
Пакет удалённого клиента приходит в под VPN с внутренним источником в диапазоне туннеля, скажем 10.90.0.42. Когда под пересылает этот пакет к ClusterIP или IP пода, источник могут переписать три разных механизма. Правило masquerade CNI узла покрывает трафик, который под отправляет за пределы CIDR кластера. Запись conntrack kube-proxy на целевом узле покрывает сам переход к Service. Прокси, завершающий соединение, вообще не пересылает пакет, поэтому источник, который вы в итоге видите, принадлежит прокси.
Каждый из них живёт в своём слое, поэтому одно поле Service почти никогда не исправляет весь путь.
externalTrafficPolicy на публичном Service VPN решает только то, что происходит с внешним соединением: Local сохраняет удалённый адрес на узле, который его получил, а Cluster позволяет kube-proxy передать пакет другому узлу и замаскировать его там. Эта настройка управляет слушателем, к которому подключаются ваши клиенты. Она ничего не говорит о расшифрованном пакете, который ваш процесс VPN затем направляет в кластер.
Три условия, которые решают спор
Я задаю одни и те же три вопроса в одном и том же порядке каждый раз, когда это возникает, потому что первый обычно завершает обсуждение. Отвечайте на них для конкретной нагрузки, а не для кластера в целом. Два кластера в одной компании могут прийти к разным ответам, и оба могут быть верными.
| Question | Preserve | SNAT |
|---|---|---|
| Does the backend enforce policy per client? | Yes, the address is the identity | Only if a trusted proxy supplies identity |
| Can the cluster route 10.90.0.0/24 back to a stable gateway? | Required | Not needed |
| Is the workload a forwarder or a proxy? | Forwarder | Proxy is fine |
Если бэкенд отвечает да на первый вопрос и нет на второй, у вас сетевая работа, а не манифест для правки. Если третья строка говорит прокси, адрес никогда не должен был выжить, и утверждать обратное стоит недели захвата пакетов.
Что режим preserve требует от сети
Сохранение источника означает, что целевой узел должен возвращать трафик на 10.90.0.42 через активный VPN-шлюз. Пул VPN не является CIDR кластера, поэтому ни один CNI не маршрутизирует его за вас по умолчанию. Вы добавляете маршрут сами, а затем следите, чтобы конечная точка шлюза, на которую он указывает, переживала перепланирование.
ip route add 10.90.0.0/24 via 10.244.3.17 dev eth0
sysctl -w net.ipv4.conf.eth0.rp_filter=2
Следующий шаг — это адрес пода, а адреса подов перемещаются. Направьте маршрут на VIP Service или на адрес узла, который остаётся на месте, либо примите, что будете гоняться за шлюзом после каждого выселения. Фильтрация обратного пути — другая ловушка: строгий режим отбрасывает пакеты, обратный путь которых не совпадает с интерфейсом, на который они пришли, и это в точности форма сохранённого VPN-потока.
Слабая валидация часто является разницей между работающим обратным путём и ответами, которые исчезают после выхода из бэкенда. Правила masquerade на узле VPN тоже должны исключать диапазон туннеля, иначе пересланный пакет уходит с адресом пода, независимо от того, какой маршрут вы построили. Предпочитайте выражать это исключение в собственной конфигурации CNI вместо ручного редактирования iptables, потому что агент перезаписывает свои цепочки при перезапуске, и ваше рукописное правило живёт ровно до следующего обновления.
NetworkPolicy — это контроль доступа, а не маршрутизация. Ужесточение политики никогда не восстановит адрес, который masquerade уже заменил.
Сколько стоит SNAT и как это записать
NAT источника к кластеру — более дешёвый дизайн, и это не ошибка. Бэкенд видит адрес пода или узла VPN, записи согласуются между собой, и обратный маршрут не должен существовать. Вы теряете возможность различать двух клиентов на сетевом уровне, поэтому квоты, запреты и следы аудита должны приходить откуда-то ещё.
Обычно это «откуда-то ещё» — приложение: токен сессии, подписанный заголовок или строка протокола PROXY, написанная прокси, которым вы управляете. Они дают получателю идентичность, которой он может доверять только тогда, когда прокси находится на пути и заголовок нельзя задать со стороны клиента. Будьте явны в runbook, какой из них применяется, потому что следующий инженер будет предполагать, что адрес в журнале — это клиент. Это не так, и одного инцидента достаточно, чтобы сделать это допущение дорогим.
Обмен остаётся честным, пока он записан.
Проверки, которые отделяют работающий путь от удачливого
Тестируйте свежим соединением, а не кэшированным, и тестируйте в обоих направлениях. Несколько сбоев выглядят перемежающимися только потому, что новые потоки идут переписанным путём.
Захватите tuple в трёх точках во время одного авторизованного запроса: сразу после декапсуляции, на выходном интерфейсе пода VPN и на бэкенде. Если источник меняется между вторым и третьим захватом, причина ниже по потоку от пода. Если меняется до второго, сам под переводит.
Затем удалите под VPN и повторите тест, пока он перепланируется. Сохранённый путь, который ломается при выселении, недоделан, и то же самое верно для правила NAT, привязанного к адресу, которого больше нет. Наконец, отправьте один запрос из источника, который, как вы ожидаете, будет отклонён, и подтвердите, что отказ исходит от политики, а не от отсутствующего маршрута.