Безопасность современной IT-инфраструктуры неразрывно связана с контейнеризацией, где Docker остается доминирующей платформой для развертывания приложений. Однако глубокая интеграция Docker с сетевым стеком Linux порождает специфические риски, наиболее известным из которых является обход правил Uncomplicated Firewall (UFW). Для профессионального сообщества понимание этого механизма является важным, так как стандартные методы настройки защиты хоста часто оказываются неэффективными в контексте изолированных сред. Проблема заключается не в дефекте программного обеспечения, а в фундаментальной архитектуре взаимодействия Docker с подсистемой Netfilter ядра Linux.
- Архитектурная деконструкция сетевого стека: Netfilter, Iptables и Docker
- Практическая верификация уязвимости
- Использование цепочки DOCKER-USER
- Управление правилами доступа: Команда ufw route
- Автоматизация через ufw-docker (Chaifeng)
- Альтернативные подходы к безопасности портов
- Глубокое погружение: Отключение управления iptables
- Реалии: Переход на nftables и Docker 29+
- Комплексные меры безопасности контейнеров
- Мониторинг и аудит сетевой активности
- Заключение
Архитектурная деконструкция сетевого стека: Netfilter, Iptables и Docker
Для детального понимания того, как контейнеры обходят брандмауэр, необходимо проанализировать путь прохождения сетевого пакета через ядро. Netfilter представляет собой фреймворк внутри ядра Linux, который позволяет перехватывать и манипулировать сетевыми пакетами. UFW выступает в роли упрощенного интерфейса для управления правилами этого фреймворка, ориентируясь преимущественно на цепочку INPUT таблицы filter.
Docker, в свою очередь, использует Netfilter для реализации трансляции сетевых адресов (NAT) и маршрутизации трафика между физическими интерфейсами хоста и виртуальными интерфейсами контейнеров. В момент публикации порта контейнера (например, через флаг -p 8080:80) Docker вносит изменения непосредственно в таблицы nat и filter, создавая собственные цепочки, такие как DOCKER и DOCKER-INGRESS.
Механизм обхода: почему стандартные правила UFW не работают
Когда внешний пакет поступает на сетевой интерфейс, он попадает в цепочку PREROUTING таблицы nat. Здесь Docker применяет правило Destination NAT (DNAT), которое переписывает адрес назначения пакета с внешнего IP-адреса хоста на внутренний IP-адрес контейнера. После этого этапа пакет направляется в цепочку FORWARD таблицы filter, поскольку ядро понимает, что пакет предназначен не для локального процесса на хосте, а для пересылки на другой сетевой интерфейс (виртуальный мост docker0).
Стандартные правила UFW, создаваемые командами вроде ufw deny 8080, размещаются в цепочке INPUT. Пакеты, прошедшие через DNAT и направленные в FORWARD, никогда не попадают в цепочку INPUT. Таким образом, брандмауэр UFW физически не видит этот трафик, и он беспрепятственно достигает контейнера. Это создает иллюзию безопасности: администратор видит статус DENY в выводе UFW, но порт остается открытым для всего мира.

| Этап обработки пакета | Таблица Netfilter | Цепочка | Действие Docker / UFW |
|---|---|---|---|
| Вход пакета | raw | PREROUTING | Первичный анализ |
| Трансляция адреса | nat | PREROUTING | Docker выполняет DNAT (подмена IP) |
| Фильтрация хоста | filter | INPUT | Здесь работают правила ufw allow/deny |
| Маршрутизация (Forward) | filter | FORWARD | Docker разрешает проход пакета |
| Выход пакета | nat | POSTROUTING | Маскарадинг (SNAT) |
Практическая верификация уязвимости
Для подтверждения проблемы на сервере под управлением Ubuntu или Debian рекомендуется провести практический эксперимент. Запуск стандартного веб-сервера в контейнере с пробросом порта покажет реальное состояние дел.
Запустите контейнер:
docker run -d --name test-web -p 8080:80 nginx:alpineНастройте UFW на блокировку порта:
sudo ufw deny 8080/tcpПроверьте статус:
sudo ufw statusВ выводе будет указано, что порт 8080 заблокирован.
Попробуйте получить доступ к порту с другого компьютера:
curl http://<IP_сервера>:8080В большинстве конфигураций по умолчанию сервер ответит успешно. Для глубокого анализа следует изучить активные правила iptables:
sudo iptables -L DOCKER -n -v В этом списке будут видны правила ACCEPT, которые Docker добавил автоматически, и счетчики пакетов, подтверждающие прохождение трафика в обход UFW.
Использование цепочки DOCKER-USER
Наиболее эффективным и официально рекомендованным методом решения является использование цепочки DOCKER-USER. Эта цепочка была создана разработчиками Docker специально для того, чтобы системные администраторы могли добавлять свои правила фильтрации, которые будут выполняться до того, как сработают автоматические правила Docker.
Внедрение этого решения требует модификации файла конфигурации UFW /etc/ufw/after.rules. Этот файл содержит правила, которые загружаются после основных правил UFW и позволяют использовать синтаксис iptables напрямую.
Реализация «патча» DOCKER-USER
Необходимо добавить следующий блок кода в конец файла /etc/ufw/after.rules (перед финальной строкой COMMIT, если она относится к таблице filter):
# BEGIN UFW AND DOCKER INTEGRATION
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
# Направляем трафик Docker на проверку в пользовательскую цепочку UFW
-A DOCKER-USER -j ufw-user-forward
# Разрешаем установленные и связанные соединения (Established/Related)
-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
# Разрешаем внутренний трафик между контейнерами в стандартной сети bridge
-A DOCKER-USER -i docker0 -j ACCEPT
# Разрешаем трафик из доверенных внутренних подсетей (опционально)
-A DOCKER-USER -s 10.0.0.0/8 -j RETURN
-A DOCKER-USER -s 172.16.0.0/12 -j RETURN
-A DOCKER-USER -s 192.168.0.0/16 -j RETURN
# Блокируем весь остальной входящий трафик к портам Docker и логируем его
-A DOCKER-USER -j ufw-docker-logging-deny
# Правила логирования и сброса
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix " "
-A ufw-docker-logging-deny -j DROP
COMMIT
# END UFW AND DOCKER INTEGRATIONПосле сохранения изменений необходимо перезагрузить брандмауэр:
sudo ufw reloadС этого момента все внешние запросы к опубликованным портам Docker будут блокироваться по умолчанию, так как они попадают в цепочку DOCKER-USER и сбрасываются правилом DROP.

Управление правилами доступа: Команда ufw route
После применения вышеописанного патча стандартная команда ufw allow <порт> перестанет работать для контейнеров, так как она по-прежнему создает правила в цепочке INPUT. Для управления доступом к портам контейнеров теперь необходимо использовать команду ufw route.
Синтаксис команды ufw route позволяет точно определить, какой внешний трафик может проходить через хост к внутренним интерфейсам Docker.
| Задача | Команда |
|---|---|
| Разрешить доступ к порту 80 всех контейнеров | sudo ufw route allow proto tcp from any to any port 80 |
| Разрешить доступ к конкретному контейнеру по IP | sudo ufw route allow proto tcp from any to 172.17.0.2 port 80 |
| Разрешить доступ только с определенного IP-адреса | sudo ufw route allow proto tcp from 203.0.113.50 to any port 3306 |
| Удалить правило доступа | sudo ufw route delete allow proto tcp from any to any port 80 |
Важно понимать, что при использовании ufw route allow для порта, проброшенного через -p 8080:80, в правиле следует указывать именно внутренний порт контейнера (80), а не внешний порт хоста (8080), так как фильтрация происходит в цепочке FORWARD уже после того, как DNAT изменил порт назначения.
Автоматизация через ufw-docker (Chaifeng)
Для тех, кто ищет более простое и автоматизированное решение, проект ufw-docker от разработчика Chaifeng предлагает готовый инструмент, который берет на себя всю сложность настройки after.rules.
Установка и настройка инструмента
Утилита представляет собой shell-скрипт, который интегрируется в систему и предоставляет удобный CLI для управления правилами.
Загрузите и установите скрипт :
sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-dockerВыполните установку необходимых правил в UFW:
sudo ufw-docker installЭта команда автоматически добавит необходимые цепочки и правила в /etc/ufw/after.rules, обеспечивая блокировку внешнего доступа к контейнерам по умолчанию.
Перезагрузите UFW:
sudo systemctl restart ufwТеперь вы можете использовать команды типа sudo ufw-docker allow <имя_контейнера> <порт> для открытия доступа. Инструмент автоматически определит текущий IP-адрес контейнера и создаст нужные правила маршрутизации. Это избавляет от необходимости отслеживать динамические IP-адреса контейнеров при каждом перезапуске.
Альтернативные подходы к безопасности портов
Помимо манипуляций с брандмауэром на уровне хоста, существуют архитектурные паттерны, которые минимизируют риски безопасности по умолчанию.
Привязка к Loopback-интерфейсу
Наиболее надежный и простой способ защиты чувствительных сервисов (например, баз данных) — это их публикация только на интерфейсе localhost. Если порт привязан к 127.0.0.1, он физически недоступен из внешней сети, даже если Docker обходит UFW.
Пример запуска контейнера:
docker run -d -p 127.0.0.1:5432:5432 postgres:16-alpineВ конфигурации docker-compose.yml :
services:
db:
image: postgres:16
ports:
- "127.0.0.1:5432:5432"Этот подход рекомендуется для всех внутренних сервисов, которые не должны иметь прямого доступа из интернета.
Паттерн «Обратный прокси» (Gateway Pattern)
Современные практики DevOps предполагают использование единой точки входа для всего веб-трафика. В этой схеме только один контейнер (например, Nginx, Traefik или Caddy) имеет опубликованные порты 80 и 443 на внешнем интерфейсе 0.0.0.0. Все остальные приложения работают во внутренних сетях Docker и не публикуют порты на хосте вовсе.
Это позволяет:
- Централизованно управлять SSL/TLS сертификатами.
- Настраивать Rate Limiting и защиту от DDoS в одном месте.
- Реализовать дополнительную аутентификацию перед доступом к внутренним приложениям.
- Полностью изолировать приложения от внешнего мира, используя механизмы Docker Network.

Глубокое погружение: Отключение управления iptables
В Docker существует возможность полностью запретить демону изменять правила iptables. Это делается путем добавления "iptables": false в файл /etc/docker/daemon.json.
Хотя на первый взгляд это кажется идеальным решением конфликта с UFW, на практике это приводит к серьезным побочным эффектам, которые могут нарушить работу всей системы.
Последствия отключения управления iptables:
- Отсутствие доступа к интернету из контейнеров: Docker не сможет создать правила маскарадинга (MASQUERADE), что означает, что контейнеры не смогут обновлять пакеты или обращаться к внешним API.
- Неработающая публикация портов: Флаг
-pперестанет работать, так как Docker не будет создавать правила DNAT. - Нарушение изоляции сетей: Без правил
iptablesизоляция между различными сетями Docker может быть нарушена, что позволяет трафику свободно проходить между ними. - Необходимость ручной настройки NAT: Администратору придется вручную прописывать десятки правил трансляции для каждой создаваемой сети и каждого опубликованного порта.
| Параметр | По умолчанию (true) | Отключено (false) |
|---|---|---|
| Удобство настройки | Высокое (автоматика) | Низкое (ручной труд) |
| Контроль безопасности | Низкий (обход UFW) | Полный (ручное управление) |
| Работа сети «из коробки» | Да | Нет (требует доработки) |
| Рекомендация для продакшена | Да (с патчем DOCKER-USER) | Нет (только для экспертов) |
Реалии: Переход на nftables и Docker 29+
В 2025–2026 годах экосистема Linux завершает переход от классического iptables к более производительному и гибкому nftables. Большинство современных дистрибутивов (Debian 12/13, Ubuntu 24.04/26.04) используют nftables по умолчанию.
Docker версии 29.0.0 и новее внедрил официальную (хотя на текущий момент экспериментальную) поддержку бэкэнда nftables. При активации опции "firewall-backend": "nftables" в daemon.json поведение системы существенно меняется :
- Отсутствие DOCKER-USER: В реализации
nftablesдля Docker на текущий момент отсутствует прямая аналогия цепочкиDOCKER-USER. Вместо этого рекомендуется создавать отдельные таблицыnftablesс приоритетом выше, чем у таблиц Docker, для выполнения фильтрации. - IP Forwarding: При использовании бэкэнда
nftablesDocker больше не включает автоматический форвардинг трафика на уровне ядра, если он отключен. Это требует от администратора явной настройки черезsysctl. - Iptables-nft: Большинство систем продолжают использовать слой совместимости
iptables-nft, который транслирует командыiptables(и UFW) в правилаnftables. Это позволяет старым методам защиты (таким как патчDOCKER-USER) продолжать работать, но может создавать сложности при отладке из-за наличия «виртуальных» цепочек.

Комплексные меры безопасности контейнеров
Решение проблемы с брандмауэром — лишь одна часть стратегии защиты. Настоящая безопасность Docker рассматривается как многоуровневая система (Defense in Depth).
Ограничение ресурсов и привилегий
Контейнеры не должны иметь неограниченный доступ к ресурсам хоста. Это предотвращает атаки типа «отказ в обслуживании» (DoS) и попытки захвата хоста.
- Лимиты памяти и CPU: Всегда указывайте лимиты в
docker-compose.yml, чтобы скомпрометированный контейнер не смог парализовать весь сервер. - Read-only файловая система: Используйте флаг
--read-only, чтобы запретить запись в корневую файловую систему контейнера. Это лишит злоумышленника возможности скачать вредоносные скрипты или изменить код приложения. - Drop Capabilities: Ядро Linux предоставляет богатый набор привилегий. Большинству приложений не нужно уметь менять системное время или настраивать сетевые интерфейсы. Используйте
--cap-drop allи добавляйте только необходимые разрешения.
Безопасность образов и цепочка поставок
Безопасность начинается еще на этапе сборки.
- Минимальные базовые образы: Используйте Alpine Linux или Distroless-образы. Чем меньше инструментов (типа
curl,wget,sh) доступно внутри контейнера, тем сложнее атакующему закрепиться в системе. - Сканирование на уязвимости: Интегрируйте инструменты сканирования (Trivy, Grype, Snyk) в ваш CI/CD пайплайн. Это позволит обнаруживать критические уязвимости (CVE) в библиотеках до того, как они попадут в продакшен.
- Запуск от имени не-root пользователя: По умолчанию процессы в контейнере запускаются от имени
root. Всегда создавайте системного пользователя в Dockerfile и используйте инструкциюUSER.

Мониторинг и аудит сетевой активности
Для поддержания высокого уровня безопасности необходимо регулярно проводить аудит системы. Ключевыми инструментами являются:
- Docker Bench for Security: Скрипт, проверяющий конфигурацию хоста и демона Docker на соответствие стандартам CIS (Center for Internet Security).
- Nmap аудит: Регулярное внешнее сканирование ваших серверов поможет обнаружить порты, которые были случайно открыты в обход брандмауэра.
- IDS/IPS системы: Инструменты вроде
CrowdSecилиFail2banмогут анализировать логи Docker и UFW, автоматически блокируя IP-адреса злоумышленников, пытающихся подобрать пароли к вашим сервисам.
Заключение
Проблема обхода UFW контейнерами Docker — это классический пример того, как удобство использования (автоматическая настройка сети) вступает в конфликт с требованиями безопасности. Для обеспечения надежной защиты ваших проектов следует придерживаться комплексного подхода.
Итоговый алгоритм настройки:
- Примените патч DOCKER-USER: Это вернет контроль над транзитным трафиком в UFW и закроет порты по умолчанию.
- Используйте ufw route: Перейдите на явное разрешение доступа только для необходимых сервисов.
- Изолируйте чувствительные данные: Базы данных и кэши должны слушать только
127.0.0.1. - Внедрите Reverse Proxy: Используйте архитектуру «шлюза» для всех публичных веб-приложений.
- Автоматизируйте проверки: Интегрируйте сканеры образов и аудит конфигураций в ваш процесс разработки и эксплуатации.
Безопасность не является конечной точкой настройки, это непрерывный процесс адаптации к новым угрозам и изменениям в технологическом стеке. Понимание механизмов Netfilter и правильная конфигурация UFW — это фундамент, на котором строится стабильная и защищенная инфраструктура любого IT-проекта.
Было ли это полезно?
1 / 0