Docker может обойти UFW: почему lab/staging нельзя просто публиковать наружу
Правильная граница: публичный интернет не видит lab ports, control plane видит их через allowlist.
Коротко: Если контейнер с учебно-уязвимым приложением слушает 0.0.0.0, он становится настоящим production-рискoм, даже если команда считала его внутренней лабораторией.

Проблема

Docker по умолчанию управляет собственными NAT-правилами. Поэтому ситуация 'ufw deny' не всегда означает, что порт действительно закрыт снаружи: published port может пройти через Docker-цепочки раньше ожидаемого фильтра.

Это особенно опасно для security-лабораторий. DVWA, Juice Shop, тестовые API и временные admin UI должны быть доступны только runner/control plane, а не всему интернету.

Решение

Для Docker-хостов нужен отдельный exposure check: docker ps, ss, iptables/nft DOCKER-USER, внешний curl с недоверенного IP и проверка allowlist с control plane.

Базовая модель: контейнер может слушать локально, но вход извне разрешается только через reverse proxy, VPN или control plane. Для прямой публикации используется DOCKER-USER deny-by-default и точечные RETURN для доверенных адресов.

Что проверить руками

  • Все published ports: 0.0.0.0:port и [::]:port.
  • Есть ли DOCKER-USER правила до Docker accept rules.
  • Открываются ли lab ports с внешнего адреса, который не входит в allowlist.
  • Задокументирована ли причина существования каждого тестового контейнера.

Как это должно попадать в отчёт

  • Открытый lab/staging порт - это не косметика, а риск компрометации тестовой среды и pivot в control plane.
  • Finding должен содержать внешний proof of reachability, список контейнеров, firewall path и конкретный retest: внешний адрес получает timeout/403, control plane продолжает получать 200.

Безопасный пример: инвентаризация Docker-портов и DOCKER-USER

#!/usr/bin/env bash
set -euo pipefail

echo "[published containers]"
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}'

echo
echo "[listening ports]"
ss -lntup | awk 'NR==1 || /docker-proxy|:3000|:3001|:3002|:8080|:9090/'

echo
echo "[docker-user policy]"
iptables -S DOCKER-USER 2>/dev/null || echo "DOCKER-USER chain not found"

echo
echo "retest idea: run curl from an untrusted network and from the control plane; the result must differ by policy, not by accident."
Этическая рамка: материал предназначен для defensive security, легального аудита собственных систем, подготовки remediation и обучения в контролируемой среде.