ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Docker: iptables vs nftables — как не сломать сеть контейнеров и firewall

Docker автоматически правит правила файрвола: добавляет цепочки, NAT и проброс портов. Из-за различий iptables-legacy и iptables-nft возникают «правила есть, но не работают», конфликты с firewalld и лишняя доступность контейнеров. Разберём диагностику и контроль.
Docker: iptables vs nftables — как не сломать сеть контейнеров и firewall

Когда на сервере появляется Docker, файрвол перестаёт быть «только вашим»: демон сам создаёт и обновляет правила для проброса портов, межконтейнерной связи и маскарадинга. На системах, где по умолчанию используется nftables (а iptables работает через совместимый бэкенд), это часто превращается в путаницу: «правила есть, но не срабатывают», «после перезагрузки всё иначе», «firewalld конфликтует», «контейнеры внезапно доступны извне».

Ниже — практическая схема: чем отличается iptables-legacy от iptables-nft, какие цепочки и правила Docker добавляет в фильтр и NAT, где находится точка контроля (DOCKER-USER), и как не получить «две параллельные реальности» при настройке firewall.

Ключевая идея: Docker управляет правилами, но оставляет вам точку контроля

Docker исторически «заточен» под iptables и ожидает, что сможет:

  • создавать свои цепочки (например, DOCKER, DOCKER-ISOLATION-STAGE-1, DOCKER-ISOLATION-STAGE-2);
  • встраиваться в стандартные цепочки (INPUT/FORWARD/OUTPUT, а также PREROUTING/POSTROUTING в NAT);
  • динамически обновлять правила при старте/остановке контейнеров и публикации портов (-p 80:80 и т.п.).

На современных дистрибутивах обычно встречаются два режима iptables:

  • iptables-legacy — классический стек iptables;
  • iptables-nft — iptables как «фронтенд», который пишет правила в nftables (объекты nft в семействах ip/ip6).

Для вас это означает одно: управлять и диагностировать нужно в одной выбранной плоскости. Если система использует iptables-nft, то правки «чистого nft ruleset» поверх того, что меняют Docker и firewalld, быстро превращаются в расследования «почему так, если я всё закрыл».

iptables vs nftables в контексте Docker: что ломается чаще всего

1) «Я настроил nftables, а Docker всё равно открыл порт»

Причина почти всегда в том, что публикация порта контейнера — это не «вход на хост» (INPUT), а связка DNAT+FORWARD:

  • DNAT в nat/PREROUTING отправляет трафик с порта хоста на IP контейнера;
  • filter/FORWARD решает, пропустить ли этот трафик дальше в docker-bridge.

Если вы усиливаете только INPUT, а FORWARD оставляете «как получится», порт может стать доступен извне даже при «закрытом» хосте.

2) «Я запретил всё в iptables, но контейнеры всё равно доступны»

Типичный сценарий «двух миров»: вы правите nftables напрямую, а смотрите iptables (или наоборот). Итог — кажется, что «правил нет», хотя они живут в другом месте. Диагностика должна быть консистентной: если у вас iptables-nft, проверяйте и iptables-вывод, и итоговый ruleset nftables.

3) «firewalld и Docker дерутся за FORWARD»

firewalld тоже динамически управляет правилами и цепочками. Конфликт чаще проявляется так:

  • FORWARD внезапно становится DROP по умолчанию, и контейнеры теряют сеть;
  • меняются приоритеты, и jump в docker-цепочки оказывается не там, где вы ожидали.

Вывод iptables с цепочкой FORWARD и переходом в DOCKER-USER для контроля доступа к контейнерам

Если Docker для вас — основа инфраструктуры (reverse proxy, очереди, базы, мониторинг), удобнее держать это на предсказуемом сервере, где вы полностью контролируете ядро и сетевые политики. Для таких задач обычно выбирают VDS с понятной сетевой конфигурацией и доступом к системным настройкам.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Какие цепочки создаёт Docker и где искать точку контроля

С практической точки зрения держите в голове три слоя, где обычно «живёт проблема»:

  1. Фильтрация транзита (цепочка FORWARD и дочерние docker-цепочки).
  2. NAT (DNAT на входе и маскарадинг на выходе).
  3. Пользовательская вставка — цепочка DOCKER-USER.

DOCKER-USER: зачем она нужна и как её использовать

DOCKER-USER — «официальный» механизм, который Docker оставляет администратору. Docker добавляет прыжок из FORWARD в DOCKER-USER раньше, чем в свои внутренние цепочки. Это позволяет вводить глобальные политики доступа к контейнерам так, чтобы Docker их не перетирал при пересоздании контейнеров и сетей.

Если нужно ограничить доступ к опубликованным контейнерам по IP/подсети/интерфейсу, начинайте с DOCKER-USER. Это стабильнее, чем редактировать цепочку DOCKER вручную.

Пример: разрешить доступ к опубликованным портам контейнеров только с одной подсети, а остальное запретить (работает и при iptables-nft):

iptables -N DOCKER-USER
iptables -C FORWARD -j DOCKER-USER 2>/dev/null || iptables -I FORWARD 1 -j DOCKER-USER
iptables -F DOCKER-USER
iptables -A DOCKER-USER -s 203.0.113.0/24 -j RETURN
iptables -A DOCKER-USER -j DROP

Логика тут важнее конкретных значений: RETURN возвращает управление в основной поток docker-правил (то есть «разрешаем продолжить обработку»), а финальный DROP режет всё, что не попало под ваши условия.

Почему нельзя «надежно» править цепочку DOCKER

Цепочка DOCKER и цепочки изоляции bridge-сетей принадлежат Docker. При изменении сетей, публикации портов и перезапуске демона правила будут пересозданы, и ручные правки либо исчезнут, либо окажутся в неправильном порядке.

NAT Docker: как устроен проброс портов и где применяются правила

Когда вы публикуете порт контейнера командой вида docker run -p 80:80 ..., Docker обычно делает две вещи:

  • добавляет DNAT в nat/PREROUTING (и часто в nat/OUTPUT для локального доступа), чтобы трафик на порт хоста попадал на IP контейнера;
  • добавляет или обновляет разрешающие правила в filter/FORWARD, чтобы пакет прошёл транзитом в bridge-сеть.

Дополнительно для исходящего трафика контейнеров «в интернет» включается маскарадинг (обычно MASQUERADE в nat/POSTROUTING), если контейнеры сидят за приватным docker-bridge и наружу выходят через IP хоста.

Отсюда и типовой «провал»: админ усиливает INPUT (всё закрыто), публикует контейнерный порт, и он становится доступен извне через DNAT+FORWARD, хотя на уровне INPUT вы действительно «ничего не открывали».

Если хотите глубже понять, как именно Docker встраивается в цепочки и почему порядок обработки решает, посмотрите материал как Docker взаимодействует с firewall и куда попадает трафик.

Как понять, что у вас: iptables-legacy или iptables-nft

Сначала определите бэкенд iptables:

iptables --version
nft --version

Если в версии iptables есть пометка про nft, значит команды iptables управляют nftables-правилами. Тогда диагностика должна включать и просмотр через iptables, и итоговый ruleset nft:

iptables -S
iptables -t nat -S
nft list ruleset

Практическое правило: не смешивайте «ручной nft ruleset» и «ручной iptables ruleset», пока не договорились сами с собой, кто источник правды. Иначе получите ситуацию, где вы правите одно, а работает другое.

Практические стратегии: как жить с Docker на nftables без сюрпризов

Стратегия A: оставить Docker управление iptables (iptables-nft) и фильтровать через DOCKER-USER

Для одиночного сервера это обычно самый надёжный вариант: Docker пишет свои правила, а вы накладываете политику доступа в DOCKER-USER. Плюсы:

  • публикация портов работает «из коробки»;
  • межконтейнерная связь не ломается;
  • ваши ограничения не перетираются при пересоздании контейнеров.

Стратегия B: отключить управление iptables у Docker и описать правила самостоятельно

Иногда нужен полный контроль: строгие политики ingress/egress, несколько аплинков, нестандартный NAT, собственные таблицы nftables, сложный routing-policy. Тогда можно отключить авто-правила Docker параметром iptables в конфиге демона.

Пример /etc/docker/daemon.json:

{
  "iptables": false
}

После этого вам придётся самостоятельно обеспечить:

  • форвардинг между интерфейсами (хост ⇄ docker-bridge);
  • DNAT для опубликованных сервисов (или отказаться от -p и публиковать сервисы через reverse proxy на хосте);
  • маскарадинг для исходящего трафика контейнеров.

Отключайте docker-iptables только если готовы поддерживать сетевую модель руками и понимаете, как ваши docker-сети маршрутизируются на хосте.

firewalld и Docker: как избежать конфликтов и «плавающих» правил

С firewalld обычно две задачи: сохранить предсказуемость и не потерять сеть контейнеров после обновления или перезагрузки. На практике помогают три принципа:

  • Не дублировать управление одной плоскостью. Если firewalld управляет nftables, а Docker пишет через iptables-nft, это терпимо. Но если вы ещё и руками правите nft ruleset, становится трудно объяснять приоритеты.
  • Проверять политику FORWARD. Если после включения firewalld контейнеры теряют интернет, чаще всего причина именно в FORWARD и зонах.
  • Фиксировать вход на контейнеры через DOCKER-USER. Даже с firewalld это удобная точка: вы фильтруете транзит к docker-bridge в одном месте.

Для быстрой диагностики «почему контейнер недоступен снаружи» соберите факты по шагам: опубликован ли порт, куда он DNAT’ится, и проходит ли FORWARD:

docker ps --format '{{.Names}}	{{.Ports}}'
iptables -t nat -S | grep -E 'DOCKER|dport'
iptables -S FORWARD
iptables -S DOCKER-USER
nft list ruleset

Если вы раздаёте контейнерные сервисы наружу, не забывайте про TLS: проще и правильнее сразу поставить сертификаты и завершать HTTPS на reverse proxy. Для продакшена удобно держать под рукой SSL-сертификаты, чтобы не оставлять панели и API «на голом HTTP».

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Типовые кейсы и решения

Кейс 1: контейнер доступен «всем», хотя нужен доступ только из локальной сети

Не пытайтесь закрыть это через INPUT. Добавьте ограничение в DOCKER-USER по источнику и в конце поставьте DROP. При необходимости дополнительно фильтруйте по входному интерфейсу (например, разрешать только с интерфейса внутренней сети).

Кейс 2: после включения firewalld контейнеры потеряли доступ наружу

Проверьте, что форвардинг разрешён и docker-bridge находится в ожидаемой зоне. Важно понимать: трафик контейнеров чаще проходит через FORWARD, а не через OUTPUT хоста. Поэтому «разрешить исходящие» для хоста не равно «разрешить исходящие для контейнеров».

Кейс 3: вы используете чистый nftables ruleset и хотите предсказуемые правила

Выберите один источник правды. Либо оставьте iptables-nft и управляйте через iptables/DOCKER-USER (и не пишите параллельно свои nat/forward в nft), либо отключите iptables у Docker и полностью опишите NAT/forward в nftables сами. «Смешанный режим», где часть правил вносит Docker, часть — firewalld, часть — ваши nft-скрипты, почти всегда заканчивается ночными расследованиями.

Схема прохождения трафика к опубликованному порту Docker через DNAT и FORWARD

Мини-чеклист: что проверить, если Docker и firewall не дружат

  1. Бэкенд iptables: iptables --version.
  2. Прыжок в DOCKER-USER из FORWARD и его порядок относительно остальных правил.
  3. Правила NAT от Docker: DNAT в PREROUTING, MASQUERADE в POSTROUTING.
  4. Не режет ли firewalld forward: смотрите итоговый ruleset, а не только список «разрешённых сервисов».
  5. IPv6: если включали IPv6 в Docker, отдельно проверяйте ip6tables и семейство ip6 в nftables (часто IPv4 настроен, а IPv6 либо внезапно открыт, либо полностью не работает).

Итог

Связка Docker и iptables исторически понятна и отлажена, но на современных дистрибутивах она всё чаще работает через nftables (iptables-nft). Чтобы вернуть контроль и предсказуемость, держите в голове две вещи: (1) публикация портов — это почти всегда DNAT+FORWARD, а не INPUT; (2) DOCKER-USER — лучший стабильный крючок для ваших ограничений. Дальше выбирайте стратегию: либо доверяете Docker управлять правилами и фильтруете доступ через DOCKER-USER, либо отключаете docker-iptables и берёте NAT/forward полностью на себя.

Если вы хотите усилить изоляцию контейнеров не только сетевыми правилами, но и на уровне песочницы рантайма, посмотрите материал про изоляцию контейнеров с gVisor и Firecracker.

Поделиться статьей

Вам будет интересно

Nginx DNS в Docker/Kubernetes: resolver, valid и ipv6=off без сюрпризов OpenAI Статья написана AI (GPT 5)

Nginx DNS в Docker/Kubernetes: resolver, valid и ipv6=off без сюрпризов

Когда backend в Docker или Kubernetes меняет IP, Nginx может продолжать подключаться к «старому» адресу. Разбираем, как работает D ...
DNSSEC на практике: KSK/ZSK, DS record и безопасный rollover без SERVFAIL OpenAI Статья написана AI (GPT 5)

DNSSEC на практике: KSK/ZSK, DS record и безопасный rollover без SERVFAIL

Разбираем DNSSEC на практике: как устроены KSK/ZSK и DS record, как читать DNSKEY/RRSIG, почему при ошибках появляется SERVFAIL и ...
Linux passthrough (VFIO): включение IOMMU (VT-d/AMD-Vi), проверка и типовые проблемы OpenAI Статья написана AI (GPT 5)

Linux passthrough (VFIO): включение IOMMU (VT-d/AMD-Vi), проверка и типовые проблемы

Практический разбор IOMMU в Linux для PCI passthrough: включаем VT-d/AMD-Vi в BIOS и через grub, проверяем /proc/cmdline и dmesg, ...