Короткий ответ

Если сервис слушает, ping жив, а клиент ловит timeout — сначала докажите какой именно drop. Снимите counters и лог на правиле, воспроизведите запрос, посмотрите, какая линия растёт. Добавьте точечный accept (интерфейс, src, dst, порт, state). Не делайте systemctl stop nftables, ufw disable, /ip firewall filter disable [find] на всю цепь и не ставьте allow any-any «чтобы проверить».

Различайте цепи: input — к сокету шлюза, forward — транзит LAN/DMZ, output — с самого firewall. Лечить «не открывается сайт в DMZ» правкой input бесполезно.

Плейсхолдеры: WAN 203.0.113.10, LAN 10.0.10.0/24, DMZ 10.0.30.0/24, mgmt 10.0.99.0/24. Клиент в LAN, веб в DMZ 10.0.30.10:443.

Симптомы и как отличить

Клиент 10.0.10.50 не достучится до 10.0.30.10:443 или до сервиса на самом шлюзе. curl висит, Test-NetConnection — TcpTestSucceeded False, на сервере ss показывает LISTEN.

КартинаСкорее не фильтр шлюзаКуда
Refused сразуникто не слушаетприложение, bind
Timeout, counters drop растутфильтрэта статья
Timeout, counters тихиемаршрут, VLAN, чужой NICсеть, не rule
Работает с шлюза, не с клиентаforward vs inputсмотрите forward
Работало, после IPS/GeoIP нетне классический filterIPS, GeoIP

Возможные причины

  1. Нет accept ct state established,related — ответные пакеты drop.
  2. Allow поставили ниже default drop / «deny all».
  3. Правило на in-interface=ether1 (WAN), а трафик с bridge1/VLAN LAN.
  4. Разрешили tcp 443, клиент идёт на 8443 / HTTP/3 UDP 443.
  5. Conntrack full или connection-state=invalid на асимметрии.
  6. Rate-limit / GeoIP / IPS drop маскируется под «firewall».
  7. Только table ip, клиент пришёл IPv6.

Диагностика

Backup до экспериментов. Не сбрасывайте counters на всех правилах в пик, если нет копии print stats.

1. Слушает ли сервис

На web01 в DMZ:

ss -lntup | grep ':443'
ip -br addr
curl -sS -o /dev/null -w '%{http_code}\n' --connect-timeout 2 https://127.0.0.1/

Локальный ответ при сетевом timeout — путь или фильтр, не nginx «мёртв».

2. nftables: list и счётчики

На шлюзе Ubuntu 22.04/24.04:

sudo nft list ruleset -a > /root/nft-before-$(date +%F%H%M).nft
sudo nft list counters
sudo conntrack -S

Воспроизведите запрос с клиента. Снова nft list ruleset -a: какая handle-линия с drop увеличила packets. Если на правилах нет counter — временно добавьте counter+log на копии drop, не меняя policy на accept.

# лог только нужного потока, не всего WAN
sudo nft add rule inet filter forward position 0 \
  ip saddr 10.0.10.50 ip daddr 10.0.30.10 tcp dport 443 ct state new \
  counter log prefix "FW-TRACE-443 " flags all

Смотрите journalctl -k -f / dmesg на префикс. Удалите trace-правило после съёма.

3. RouterOS 7

/ip firewall filter print stats
/ip firewall filter reset-counters-all

Повторите доступ, снова print stats. Растущий drop в forward с in-interface-list=LAN out-interface-list=DMZ — ваш кандидат. Цепь input при транзите не должна расти.

/ip firewall filter add chain=forward action=log log-prefix="TRACE443" \
  src-address=10.0.10.50 dst-address=10.0.30.10 protocol=tcp dst-port=443 \
  connection-state=new place-before=0
/log print where message~"TRACE443"

Снимите log-правило после диагностики.

4. Stateful периметр концептуально

First-match: пакет бьётся в первое совпавшее правило. Если выше стоит reject в VLAN users, нижний pass на 443 мёртв. States: если ответ идёт другим путём (два WAN, policy routing), state invalid — drop. Не отключайте filter «посмотреть pfctl»; читайте states и counters.

Отделите журналирование: если логов нет, counters всё равно работают.

Решение

Сценарий A. Нет allow в forward LAN→DMZ:443

nftables, политика forward drop:

sudo cp /etc/nftables.conf /root/nftables.conf.bak.$(date +%F)

В постоянном конфиге (не одноразовый nft add без сохранения):

  • в начале цепочки: ct state established,related,untracked accept
  • затем: iifname "lan0" oifname "dmz0" ip saddr 10.0.10.0/24 ip daddr 10.0.30.10 tcp dport 443 ct state new accept
  • в конце: counter drop с log для new с LAN, если нужно
sudo nft -c -f /etc/nftables.conf
sudo systemctl reload nftables

RouterOS:

/ip firewall filter add chain=forward action=accept \
  connection-state=established,related place-before=0
/ip firewall filter add chain=forward action=accept \
  src-address=10.0.10.0/24 dst-address=10.0.30.10 protocol=tcp dst-port=443 \
  in-interface-list=LAN out-interface-list=DMZ

Правило выше drop all.

Сценарий B. Неверный интерфейс

Сверьте iifname/in-interface с ip link / /interface print. После переименования ether1→wan1 старые правила не матчятся: пакет падает в default drop. Исправьте имена или используйте interface-list.

Сценарий C. Established забыли

Симптом: SYN проходит (иногда виден в log), данные нет, или «первый пакет ок, TCP ломается». Добавьте established,related в обе стороны по смыслу stateful (обычно в начале input и forward).

Сценарий D. Это не filter, а IPS/limit

Если counter filter тихий, а доступ нет — смотрите IPS drop и limit. Не открывайте порт any. Переведите сигнатуру в detect, уточните exception.

Сценарий E. Нужен временный доступ для проверки

Временный allow только 5-tuple заявки с комментарием и датой снятия. Не accept ip saddr 10.0.10.0/24 на всё. Календарь: удалить через N часов.

Не используйте nft flush ruleset как rollback — у вас есть файл .bak. Откат: nft -f /root/nftables.conf.bak.ДАТА.

Как проверить, что проблема устранена

С того же клиента 10.0.10.50:

curl -v --connect-timeout 5 https://10.0.30.10/
# или имя из split-dns
Test-NetConnection 10.0.30.10 -Port 443

На шлюзе counter вашего allow растёт, drop по этому 5-tuple нет. С LTE на 203.0.113.10:443 — только если матрица разрешает публикацию; LAN-сервис не должен внезапно стать WAN-open.

Если не помогло

  • Allow есть, counter ноль — shadowing, не тот VLAN, клиент не тот IP.
  • ICMP проходит, TCP нет — фильтр по protocol, MSS/PMTU, не «шлюз мёртв».
  • Через VPN нет, из офиса есть — другое in-interface (wg0), нет правила для 10.8.0.0/24.
  • Случайно открыли WAN — немедленно сузьте, см. лишние порты.
  • IDS в inline режет — статья IPS, не эта.

Профилактика

  • Каждое allow: комментарий, владелец, 5-tuple, ссылка на заявку.
  • Counter на drop и на критичных allow.
  • Change: backup + nft -c / export RouterOS.
  • Запрет «выключить firewall для проверки» в регламенте L1.
  • Мониторинг conntrack (conntrack -S, RouterOS connection print count-only).

FAQ

Почему ping есть, HTTPS нет?

ICMP echo и TCP 443 — разные правила. Пинг ничего не доказывает про сервис.

Можно ли на минуту поставить policy accept?

Нет. Сессия оборвётся — дыра останется. Counters и точечный log достаточны.

localhost работает, сеть нет — всегда firewall?

Часто bind на 127.0.0.1 или слушаете только mgmt NIC. Сначала ss, потом filter.

UFW и nft одновременно

Если ufw active, правьте через ufw, не сырой flush. На чистом nft — только nft. Не мешайте два менеджера.

FastTrack на MikroTik и «правило не логируется»

FastTrack обходит часть filter. Для диагностики временно исключите поток из FastTrack, не отключая весь firewall.