Иллюзия безопасности: UFW vs Docker
Типичная ошибка администраторов — запуск docker-compose с маппингом портов ports: - "5432:5432" на сервере, где активен UFW с политикой default deny incoming. Команда ufw status показывает, что открыты только SSH (22), HTTP (80) и HTTPS (443). Однако внешние сканеры успешно подключаются к базам данных.
Проблема не в баге, а в архитектуре Netfilter. UFW управляет цепочкой INPUT таблицы filter, которая обрабатывает только трафик, адресованный самому хосту. Docker же использует таблицу nat и цепочку PREROUTING, перехватывая пакеты до того, как ядро определит их назначение.
Механика обхода: DNAT и цепочка DOCKER
При запуске контейнеров демон Docker добавляет правила в таблицу nat. Когда внешний пакет приходит на порт 5432, он попадает в цепочку DOCKER внутри PREROUTING. Там срабатывает правило DNAT (Destination NAT), которое мгновенно переписывает адрес назначения с публичного IP сервера на внутренний IP контейнера (например, 172.18.0.2).
Поскольку адрес изменен, пакет больше не считается локальным. Ядро перенаправляет его в цепочку FORWARD таблицы filter, где правила UFW для входящего трафика (INPUT) не применяются. Трафик проходит напрямую в контейнер, минуя защиту.
Реальные угрозы и метрики
Автоматизированные боты сканируют интернет круглосуточно. По данным автора, от момента старта контейнера с открытым портом до успешного взлома проходит в среднем 1 минуту 52 секунды. Злоумышленники ищут сервисы без аутентификации или с паролями по умолчанию.
| Сервис | Порт | Тип атаки | Время до компрометации |
|---|---|---|---|
| PostgreSQL | 5432 | Шифрование данных (Ransomware) | ~2 минуты |
| Redis | 6379 | Установка майнеров (kdevtmpfsi, kinsing) | ~2 минуты |
| Qdrant | 6334 | Использование в ботнете (REPLICAOF) | ~5 минут |
Как правильно изолировать сервисы
Чтобы защитить инфраструктуру, необходимо изменить подход к маппингу портов:
- Привязка к localhost: Используйте
ports: - "127.0.0.1:5432:5432". Это сделает порт доступным только с хост-машины, и Docker не будет создавать правила DNAT для внешних интерфейсов. - Использование внутренних сетей: Общайтесь с БД через Docker network, не выставляя порты наружу вообще. Доступ извне организуйте через SSH-туннели или reverse-proxy.
- Проверка через ss: Команда
ss -tulpn | grep 5432покажет, слушает ли процессdocker-proxyна0.0.0.0(опасно) или на127.0.0.1(безопасно).
Источник: Habr ↗
