Как входящий пакет проходит через INPUT
Соединение к самому серверу попадает в цепочку INPUT таблицы filter. Правила проверяются по порядку: первое подходящее с ACCEPT, DROP или REJECT решает судьбу пакета, LOG только пишет в журнал и пропускает дальше. Переход -j в пользовательскую цепочку (ufw-user-input, f2b-sshd, DOCKER-USER) похож на вызов функции: если там ничего не решилось или сработал RETURN, проверка продолжается со следующего правила. Если до конца INPUT ничего не подошло, действует политика цепочки — та самая :INPUT DROP или ACCEPT.
Анализатор повторяет этот путь для нового соединения с произвольного адреса на каждый порт из правил и на популярные порты служб. Правила только для ESTABLISHED,RELATED новые соединения не открывают, -i lo касается только самого сервера, а правило с -s 10.0.0.0/8 открывает порт лишь для этой сети — такие порты помечены «только с». Условия, которые разобрать не удалось, не угадываются: правило помечается «может не срабатывать».
Почему порты Docker обходят ufw
docker run -p 5432:5432 добавляет в таблицу nat правило DNAT: пакет на порт 5432 сервера ещё в PREROUTING перенаправляется на адрес контейнера, например 172.17.0.2. Для ядра это уже транзитный трафик, поэтому он идёт через FORWARD, где Docker сам ставит разрешающие правила. INPUT и правила ufw (ufw deny 5432) до него не доходят — база оказывается открытой, хотя ufw status говорит обратное.
Что делать: если порт нужен только самому серверу или другим контейнерам, публикуйте его на 127.0.0.1 или не публикуйте вовсе — в сети Compose сервисы видят друг друга по имени. Если доступ нужен с определённых адресов, добавьте правила в цепочку DOCKER-USER: она проверяется первой и Docker её не перезаписывает. Учтите, что там пакет уже с портом контейнера, а исходный порт хоста проверяется через -m conntrack --ctorigdstport. Подробнее: Docker и файрвол
Как читать iptables-save
Вывод разбит на таблицы: строка *filter начинает таблицу, COMMIT заканчивает. Строки с двоеточием объявляют цепочки: :INPUT DROP [0:0] — встроенная цепочка с политикой DROP и счётчиками пакетов и байт, :ufw-user-input - [0:0] — пользовательская цепочка без политики. Дальше идут правила в порядке проверки: -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT значит «в конец INPUT: TCP на порт 22 — разрешить». Восклицательный знак инвертирует условие: ! -i docker0 — «не с интерфейса docker0».
В nft list ruleset то же самое записано блоками: table inet filter { chain input { type filter hook input priority filter; policy drop; … } }. Если там встречается «# Warning: table ip filter is managed by iptables-nft», эти правила созданы через iptables (ufw, Docker) и править их лучше теми же инструментами. Все команды — в вики.
Частые вопросы
Почему ufw deny не закрывает порт контейнера?
Docker публикует порт правилом DNAT в таблице nat. Адрес назначения меняется ещё до фильтрации, и пакет идёт в контейнер через цепочку FORWARD, а ufw и обычные правила INPUT его не видят. Ограничивайте доступ в цепочке DOCKER-USER или публикуйте порт только на 127.0.0.1 (ports: "127.0.0.1:5432:5432").
Почему лучше iptables-save, а не iptables -L?
iptables -L по умолчанию показывает только таблицу filter, скрывает интерфейсы (-i lo выглядит как «разрешить всё») и подменяет адреса именами. iptables-save печатает все таблицы, политики и правила ровно в том виде, в каком они загружены, — его можно и разобрать, и восстановить через iptables-restore.
Нужно ли вставлять ip6tables-save?
Да, если у сервера есть IPv6-адрес (проверьте ip -6 addr show scope global). iptables и ip6tables — два независимых набора правил: порт, закрытый по IPv4, может быть открыт по IPv6. В nftables таблица inet действует сразу на оба протокола.
Что значит «правило перекрыто» или «не сработает»?
Правила проверяются сверху вниз, и первое подходящее с ACCEPT, DROP или REJECT завершает проверку. Если выше стоит более широкое правило — например, ufw allow 8080 до ufw deny from 198.51.100.23 to any port 8080, — узкое правило до пакета не доходит. Его нужно поставить выше (iptables -I, ufw insert 1) или удалить.
Безопасно ли вставлять сюда правила сервера?
Разбор выполняется в браузере: правила не отправляются на сервер, не сохраняются и не попадают в адрес страницы. Адреса и имена цепочек всё равно стоит считать внутренней информацией — не пересылайте вывод в открытые чаты.
