NGINX Gateway Fabric 2.8.0: AccessPolicy закрывает клиентов по IP

4 ноября 2026 в блоге NGINX вышла заметка про AccessPolicy. Политика появилась в NGINX Gateway Fabric 2.8.0: на Gateway, HTTPRoute или GRPCRoute вешается список адресов и сетей, и Fabric решает, пускать этих клиентов или нет. Заметку написала Saloni Choudhary, рубрики Gateway, Knowledge Base и Kubernetes. Версия API gateway.nginx.org/v1alpha1, в следующих релизах поля могут сдвинуться.

AccessPolicy живёт в кластере, где вход уже принимает NGINX Gateway Fabric. На VPS, где nginx стоит из репозитория Ubuntu или Debian и отдаёт сайт через php-fpm, клиентский IP по-прежнему закрывают директивами allow и deny в конфиге виртуального хоста. Пакет nginx из apt эта политика не меняет.

Одно поле action на весь список

AccessPolicy состоит из правил. В правиле один адрес или одна сеть в записи CIDR. Поле action одно на всю политику. Deny эти адреса не пускает. Allow пускает только их, остальные отсекаются. Политика ссылается на объект в том же namespace. С Gateway она действует на каждый маршрут этого Gateway. С HTTPRoute или GRPCRoute только на выбранный маршрут. В заметке разбирают оба крепления сразу: вся соль в том, как они встречаются на одном запросе.

Примеры крутятся вокруг Gateway с именем gateway и HTTPRoute coffee. Маршрут отдаёт cafe.example.com/coffee на демо-приложение. Манифесты самого Gateway и маршрута лежат в гайде AccessPolicy. Адреса в правилах учебные, на кластере вместо них ставят свои сети.

Запрет на Gateway и офис только на coffee

Правило на все приложения вешают на Gateway. В примере два запрета: сеть 198.51.100.0/24 и отдельный адрес 203.0.113.7. Имена правил blocked-range и blocked-client. Группа цели gateway.networking.k8s.io, kind Gateway, имя gateway. В каждом правиле source.type равен IPAddress, а сам адрес лежит в source.ipAddress.address.

kubectl apply -f - <

В выводе describe смотрят условие Accepted. У принятой политики оно True. У Gateway рядом появляется AccessPolicyAffected: политика валидная и целится в этот Gateway.

Узкое правило вешают на маршрут. Allow для coffee пускает две офисные сети, 192.0.2.0/24 и 2001:db8::/32. Правила называются office-network и office-network-ipv6, цель уже HTTPRoute с именем coffee, группа та же. Проверка та же: Accepted должен быть True, у маршрута тоже будет AccessPolicyAffected. Имена gateway, coffee и правил из примера копировать незачем, если объекты в кластере называются иначе.

В гайде AccessPolicy у одной политики от 1 до 64 правил. Имя правила уникально внутри политики и похоже на DNS-метку строчными буквами, от 1 до 63 символов. В примерах гайда это office-network и rule.one. Адрес пишут в source.ipAddress.address: IPv4, IPv6 или CIDR. Если source у правила пустой, оно совпадает с любым клиентом. Несколько политик с одним и тем же action на один объект Fabric сливает в общий набор и не ставит им статус Conflicted.

Балансировщик подставляет свой адрес

До Gateway трафик обычно доходит через балансировщик или прокси. Fabric сравнивает правила с тем IP, который видит сам nginx. В такой схеме это адрес прокси. Список тогда либо отрежет балансировщик, либо пропустит всех, кто стоит за ним, одной кучей.

Исходный адрес клиента подставляют полем rewriteClientIP на ресурсе NginxProxy. Как его включить, написано в гайде PROXY protocol и RewriteClientIP.

Проверка из заметки завязана на этот режим. GW_IP и GW_PORT это адрес и порт вашего Gateway. Запрос на http://cafe.example.com с этим портом, заголовком X-Forwarded-For: 198.51.100.25 и путём /coffee получает 403 Forbidden. Адрес и так не входит в офисный список coffee, но Deny на Gateway совпадает раньше, и до allow маршрута nginx не доходит. Заголовок X-Forwarded-For в этом тесте учитывается только когда rewriteClientIP уже включён. Если клиенты из этих сетей есть на самом деле, в заметке предлагают проверить ими, а не заголовком.

Второй запрос, с X-Forwarded-For: 192.0.2.10, доходит до пода coffee. Демо отвечает адресом 10.244.0.22:8080, именем пода coffee-654ddf664b-6mwtb и URI /coffee.

Запреты складываются, Allow только сужается

Каждую AccessPolicy Fabric переписывает в директивы nginx allow и deny. Nginx идёт по ним сверху вниз и останавливается на первом совпадении. Когда политика есть и на Gateway, и на маршруте, для этого маршрута их соединяют. Маршрут без своей политики живёт по правилам Gateway. Если политик нет ни там, ни там, клиенты проходят любые.

Deny смотрят первыми, запреты с двух уровней складываются. Маршрут не откроет адрес, который Gateway уже запретил, даже если этот адрес записан в Allow маршрута. Allow от Gateway к маршруту только сужается. Расширить список Gateway своим Allow маршрут не может.

  • Deny на Gateway и Deny на маршруте: оба набора запретов.
  • Deny на Gateway и Allow на маршруте: сначала запрет Gateway, потом список маршрута.
  • Allow на Gateway и Deny на маршруте: сначала запрет маршрута, потом список Gateway.
  • Allow на Gateway, на маршруте политики нет: остаётся список Gateway.
  • На Gateway политики нет, на маршруте Allow: остаётся список маршрута.
  • Allow и Allow: только адреса, которые есть в обоих списках.

Если оба списка Allow и пересекаются не целиком, у политики маршрута условие Programmed с причиной PartiallyProgrammed. Если пересечения нет совсем, Fabric не пишет для маршрута ни одного allow, и nginx закрывает маршрут для всех. Programmed тогда False, причина Overridden. В тексте условия в обоих случаях названа Allow-политика Gateway.

У одной политики одно значение action. На один и тот же объект можно повесить несколько AccessPolicy, Fabric разбирает их вместе. Каждый Deny применяется. Если сочетание нельзя записать в nginx, например сеть Allow на маршруте не входит в список Gateway, это видно в conditions политики.

Маршрут молчит: Overridden и кривой адрес

Allow на маршруте при живом Allow на Gateway легко гасит сервис целиком. Адреса маршрута должны попадать внутрь списка Gateway. Иначе для маршрута ничего не программируется, Programmed равен Overridden, а в тексте условия стоит имя политики Gateway. Когда Allow на Gateway нет, список маршрута работает как написан.

Кривой адрес даёт другой статус. Accepted равен False, причина Invalid. Текст такой: must be a valid IPv4/IPv6 address or CIDR range. Рядом имя поля, в заметке пример spec.rules[0].source.ipAddress.address. От такой политики цель не получает AccessPolicyAffected. Адрес правят и применяют объект снова.

Поля и манифесты демо собраны в гайде AccessPolicy. Как политика стыкуется с остальными политиками Fabric, показано в обзоре custom policies. Полная схема лежит в API reference для AccessPolicy группы gateway.nginx.org/v1alpha1. Ошибки и вопросы заметка отправляет в репозиторий nginx/nginx-gateway-fabric.

На кластере с Fabric 2.8 общий запрет логично вешать на Gateway, а доступ одного приложения оставлять на его маршруте. После apply смотрят Accepted и не забывают про rewriteClientIP: иначе в сравнение попадёт адрес балансировщика, а не клиента.

Источники и ссылки


Комментарии загружаются…