Короткий ответ
Если сервис слушает, 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 нет | не классический filter | IPS, GeoIP |
Возможные причины
- Нет accept
ct state established,related— ответные пакеты drop. - Allow поставили ниже default drop / «deny all».
- Правило на
in-interface=ether1(WAN), а трафик сbridge1/VLAN LAN. - Разрешили tcp 443, клиент идёт на 8443 / HTTP/3 UDP 443.
- Conntrack full или
connection-state=invalidна асимметрии. - Rate-limit / GeoIP / IPS drop маскируется под «firewall».
- Только 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 nftablesRouterOS:
/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-dnsTest-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, RouterOSconnection 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.