Выберите продукт

UFW и Docker в 2026: NAT, published ports и безопасный хост

Практическое руководство по UFW и Docker в 2026: как трафик на published ports уходит в NAT и FORWARD, что меняет iptables-nft/nftables, и как через DOCKER-USER или localhost-публикацию безопасно закрыть порты контейнеров.
UFW и Docker в 2026: NAT, published ports и безопасный хост

Если вы ставите Docker на сервер с включённым UFW, почти неизбежно ловите сюрприз: вы «закрыли» порт в UFW, но сервис в контейнере всё равно доступен снаружи. Причина не в «дырявом UFW», а в том, как Docker программирует NAT и фильтрацию в netfilter (iptables/nftables) и куда именно попадает трафик для published ports.

Ниже разберём связку UFW+Docker в реалиях 2026 года: почему правила в INPUT не всегда влияют на опубликованные порты, что делает FORWARD, зачем существует DOCKER-USER, и как получить предсказуемый «secure docker host» без внезапных открытий после деплоя.

Почему UFW «не видит» published ports Docker

Когда вы запускаете контейнер с публикацией порта, например:

docker run -d --name app -p 8080:80 nginx

Docker делает две ключевые вещи:

  • добавляет DNAT: входящие подключения на порт 8080 хоста перенаправляет на IP контейнера в docker-сети;
  • добавляет правила фильтрации в свои цепочки (семейство DOCKER/DOCKER-USER), чтобы форвардинг до контейнера работал «из коробки».

Ключевой момент: соединение на опубликованный порт часто перестаёт быть «входом на локальный сокет хоста». После DNAT пакет начинает рассматриваться как трафик, который нужно маршрутизировать к контейнеру, а значит решающие правила оказываются в FORWARD, а не в INPUT. В результате ufw deny 8080/tcp может не дать ожидаемого эффекта, потому что вы запретили не тот путь пакета.

Практическое правило: если порт опубликован через -p, думайте не только про INPUT, но и про FORWARD и docker-цепочки.

Как выглядит путь пакета (упрощённо)

  • пакет приходит на внешний интерфейс (например, eth0);
  • в таблице NAT срабатывает PREROUTING и DNAT на IP контейнера;
  • дальше пакет проходит фильтрацию для маршрутизируемого трафика (обычно FORWARD), где Docker заранее создал «разрешающие» правила под публикацию.

Именно из-за этого связка «UFW закрывает порт» и «Docker публикует порт» без доп. мер часто ведёт к открытому порту наружу.

iptables-nft и nftables в 2026: почему становится ещё легче запутаться

На современных дистрибутивах iptables-команды обычно работают через слой совместимости iptables-nft, который программирует правила в nftables. При этом и UFW, и Docker могут продолжать «говорить iptables-командами», но фактическое состояние окажется в nftables-таблицах.

Что важно для практики:

  • UFW остаётся «оркестратором», но его модель цепочек/приоритетов не знает про Docker как «владельца» части правил;
  • Docker по умолчанию активно управляет NAT и фильтрацией (если не отключено управление iptables в демоне);
  • критично не «чем вы смотрите» (iptables/nft), а где стоит точка контроля и в каком порядке применяются правила.

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

Схема пути пакета: PREROUTING DNAT и прохождение через FORWARD и DOCKER-USER

Главный рычаг: цепочка DOCKER-USER (точка контроля до правил Docker)

Docker предусмотрел «крючок» для администраторов — цепочку DOCKER-USER. Она вызывается до правил, которые Docker генерирует под published ports. Это удобное место, чтобы реализовать политику «запрещено по умолчанию, разрешаем точечно» для доступа к контейнерам.

Идея для задачи block docker ports такая:

  • порты публикуете как обычно (или осознанно ограничиваете адресом);
  • в DOCKER-USER разрешаете только нужные источники/подсети/порты;
  • в конце ставите запрет, чтобы всё остальное не проходило в контейнеры снаружи.

Быстрая диагностика: что реально опубликовано и кто слушает

Два быстрых вопроса: «что Docker выставил наружу» и «есть ли слушающий сокет на хосте».

docker ps --format 'table {{.Names}}	{{.Ports}}'
ss -lntp | head -n 50

Если видите публикацию вроде 0.0.0.0:8080->80/tcp, это точно внешний published port. И дальше ваша точка контроля почти всегда должна учитывать FORWARD и DOCKER-USER.

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

Forward policy и UFW: почему иногда всплывает ufw route

Docker-сценарий — это маршрутизация между внешним интерфейсом хоста и виртуальными сетями контейнеров, поэтому FORWARD становится центральным. UFW исторически сфокусирован на простом периметре (INPUT/OUTPUT) и может быть консервативным к routed-трафику.

На Docker-хосте обычно одновременно важны два слоя:

  • разрешён ли IP forwarding в ядре (Docker обычно включает сам, иначе NAT контейнеров ломается);
  • какая политика и правила стоят на FORWARD (и тут появляется конфликт ожиданий между UFW и Docker).

Команда ufw route управляет именно routed-трафиком (правилами уровня FORWARD). Это может быть полезно, если вы хотите часть политики выражать «в терминах UFW», но в Docker-мире порядок правил становится критичен, а Docker всё равно добавит своё.

Если нужна предсказуемость, либо контролируйте доступ к контейнерам через DOCKER-USER, либо публикуйте порты только на localhost и выпускайте наружу через один фронтенд.

Две рабочие стратегии: localhost-публикация и фильтрация DOCKER-USER

Стратегия A: публикуем только на localhost

Самый простой и часто самый надёжный способ уменьшить площадь атаки: публиковать сервисы контейнеров только на 127.0.0.1, а наружу отдавать через один контролируемый фронтенд (reverse proxy на хосте или выделенный edge-контейнер).

Пример:

docker run -d --name app -p 127.0.0.1:8080:80 nginx

Из интернета соединение на 8080 не примется, потому что публикация привязана к loopback. UFW при этом может оставаться простым: открыть только SSH и порты фронтенда (80/443), а «внутренности» не торчат наружу.

Минусы: не всегда применимо (например, нужен прямой TCP-доступ извне к разным сервисам без прокси), и требуется аккуратная архитектура.

Стратегия B: режем внешний доступ к контейнерам в DOCKER-USER

Если вам действительно нужно публиковать порты на внешние интерфейсы (например, база доступна только из офисной подсети), используйте DOCKER-USER как явную точку контроля.

Типовой шаблон логики:

  • разрешить RELATED,ESTABLISHED, чтобы не ломать существующие соединения;
  • разрешить конкретные источники к конкретным published ports;
  • запретить остальное, что идёт «снаружи в контейнеры».

Пример для iptables-интерфейса (правила добавляйте аккуратно и проверяйте на тестовом окне; все команды однострочные):

iptables -C DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || iptables -I DOCKER-USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -C DOCKER-USER -i eth0 -p tcp -s 203.0.113.10 --dport 5432 -j ACCEPT 2>/dev/null || iptables -I DOCKER-USER 2 -i eth0 -p tcp -s 203.0.113.10 --dport 5432 -j ACCEPT
iptables -C DOCKER-USER -i eth0 -j DROP 2>/dev/null || iptables -A DOCKER-USER -i eth0 -j DROP

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

Важно: не «глушите» весь FORWARD без условий. Иначе легко сломать исходящий трафик контейнеров и межконтейнерную связность. Фильтруйте именно вход в контейнеры (как минимум по входному интерфейсу -i и по порту --dport).

Как совместить UFW и Docker без сюрпризов: практические правила

1) Зафиксируйте модель экспозиции портов

  • Модель edge proxy: наружу открыты только 80/443 (и, возможно, 22), контейнеры слушают localhost или вообще без публикации, доступ внутри docker-сетей.
  • Модель «порты наружу»: контейнеры публикуют на 0.0.0.0. Тогда обязателен контроль через DOCKER-USER или отдельную явную фильтрацию routed-трафика.

2) Разделите зоны ответственности

Рабочая схема для продакшна:

  • UFW: периметр хоста (SSH, веб-фронтенд, мониторинг).
  • Docker: NAT и маршрутизация контейнеров.
  • DOCKER-USER: политика доступа к published ports контейнеров.

3) Отлавливайте случайные публикации из Compose

Частая причина «внезапно открытого» сервиса — кто-то добавил ports: в docker-compose.yml. Для продакшна полезно договориться:

  • по умолчанию публикуем только 127.0.0.1:HOSTPORT:CONTAINERPORT;
  • или используем expose и отдаём наружу через прокси;
  • или каждое внешнее открытие подтверждаем правилами в DOCKER-USER (и документируем).
FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Типовые ошибки и быстрые проверки

Ошибка: «Сделал ufw deny, но порт открыт»

Для published ports это ожидаемо: трафик может проходить через FORWARD и docker-цепочки, а не через INPUT. Проверяйте реальный путь пакета и точку контроля.

Ошибка: «Запретил FORWARD целиком — и контейнеры потеряли интернет»

Исходящий трафик контейнеров тоже идёт через форвардинг на хосте. Если цель — «закрыть вход извне», фильтруйте по входному интерфейсу, источникам и портам, и оставляйте RELATED,ESTABLISHED.

Ошибка: «nftables показывает одно, iptables — другое»

Убедитесь, что вы не поддерживаете параллельно два набора правил и что понимаете, какой интерфейс (iptables vs nft) фактически управляет netfilter на вашей системе. Самый надёжный подход — держать одну понятную точку контроля (обычно DOCKER-USER) и регулярно проверять фактическую экспозицию портов.

Проверка опубликованных портов Docker командами docker ps и ss

Мини-чеклист для secure Docker host

  1. Явно решите, какие сервисы должны быть доступны извне, и исключите случайную публикацию портов.
  2. По умолчанию публикуйте порты на 127.0.0.1, если нет строгой необходимости слушать внешний интерфейс.
  3. Если published ports должны быть внешними, внедрите политику доступа в DOCKER-USER (разрешаем нужное, остальное режем).
  4. Периодически сверяйте фактическую экспозицию: docker ps и ss -lntp.
  5. Документируйте, какие порты опубликованы, откуда разрешён доступ и где это выражено (UFW или DOCKER-USER).

Итоги

Конфликт UFW и Docker возникает не потому, что UFW «плохой», а потому что Docker активно использует NAT и форвардинг, меняя путь пакета: опубликованные порты часто решаются в FORWARD и docker-цепочках, а не в INPUT. В 2026 году, когда повсеместны iptables-nft и nftables, особенно важно держать одну предсказуемую точку контроля и регулярно проверять фактическую экспозицию.

Для большинства серверов самый практичный подход — публиковать сервисы контейнеров только локально и отдавать наружу через контролируемый фронтенд. Если же нужны внешние published ports, используйте DOCKER-USER как место, где вы гарантированно можете закрыть доступ «по умолчанию» и разрешить ровно то, что нужно.

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

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

MySQL: Got an error reading communication packets — причины, MTU и max_allowed_packet OpenAI Статья написана AI (GPT 5)

MySQL: Got an error reading communication packets — причины, MTU и max_allowed_packet

Ошибка MySQL Got an error reading communication packets обычно связана с сетью, таймаутами или крупными пакетами. В статье — быстр ...
Kubernetes PV/PVC: StorageClass и online resize томов без простоя OpenAI Статья написана AI (GPT 5)

Kubernetes PV/PVC: StorageClass и online resize томов без простоя

Пошагово разбираем безопасное увеличение PVC в Kubernetes без простоя: какие условия нужны в StorageClass (allowVolumeExpansion), ...
WordPress тормозит: PHP, MySQL, wp-cron и autoload options — практичная диагностика OpenAI Статья написана AI (GPT 5)

WordPress тормозит: PHP, MySQL, wp-cron и autoload options — практичная диагностика

Если wp-admin «думает» по 5–20 секунд, причина обычно комплексная: wp-cron запускает тяжёлые задачи, autoload options раздулись, M ...