Перейти к содержимому
RunStack
Вики· Обновлено 29 окт. 2026 г.

Docker и файрвол

Порты из docker run -p и compose ports: открыты из интернета даже при ufw deny. Как закрыть: 127.0.0.1, DOCKER-USER, whitelist.

Коротко: порт, опубликованный Docker (-p 5432:5432, ports: ["5432:5432"]), открыт всему интернету, даже если ufw status показывает, что он закрыт.

Проверить свой сервер — анализатор правил (вставьте iptables-save) или снаружи — проверка порта.

Почему так

Пакет к контейнеру идёт не в цепочку INPUT, где живут правила ufw, а через NAT в FORWARD:

интернет → PREROUTING (nat: DOCKER, DNAT 203.0.113.5:5432 → 172.17.0.2:5432)
         → FORWARD → DOCKER-USER → DOCKER-FORWARD / DOCKER → контейнер
         (INPUT и ufw этот пакет не видят)

Docker сам добавляет разрешающие правила в FORWARD для каждого опубликованного порта. ufw ничего про них не знает.

Как закрыть — от простого к гибкому

1. Не публиковать наружу. Если к сервису ходит только nginx или другое приложение на этом же сервере:

services:
  db:
    ports:
      - "127.0.0.1:5432:5432"     # только с этого сервера

А лучше совсем без ports: — контейнеры в одной сети compose видят друг друга по имени сервиса.

2. Пускать только свои адреса — цепочка DOCKER-USER. Docker её не трогает, и она проверяется раньше его правил:

# пустить 203.0.113.10 к порту 5432 контейнеров, остальным — нет
iptables -I DOCKER-USER -p tcp -m conntrack --ctorigdstport 5432 --ctdir ORIGINAL ! -s 203.0.113.10 -j DROP

--ctorigdstport — порт, на который пришёл клиент (до DNAT). Сохранить: netfilter-persistent save. Правила в DOCKER-USER переживают перезапуск Docker.

3. Закрыть всё опубликованное, кроме нужного:

iptables -I DOCKER-USER -i eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
iptables -I DOCKER-USER 2 -i eth0 -p tcp -m conntrack --ctorigdstport 443 --ctdir ORIGINAL -j RETURN
iptables -A DOCKER-USER -i eth0 -j DROP

eth0 — внешний интерфейс (ip route get 1.1.1.1 покажет его имя).

4. Ограничить на уровне приложения. Для веб-сервисов — allow/deny в nginx перед контейнером, для сервисов RunStack — rs <сервис> access "203.0.113.10".

Чего не делать

  • "iptables": false в daemon.json — Docker перестанет управлять правилами, и у контейнеров сломается сеть и выход в интернет.
  • Править цепочки DOCKER и DOCKER-FORWARD руками — Docker перезапишет их при перезапуске.
  • Полагаться на ufw deny 5432 — см. выше.

IPv6

Если у сервера есть IPv6 и в Docker включён IPv6, то же самое нужно сделать в ip6tables (DOCKER-USER там своя).