Files
knowledge-base/decisions/2026-06-05-benelux-blackout-fw4-recovery.md

7.9 KiB
Raw Blame History

date, type, tags, status, severity
date type tags status severity
2026-06-05 decision
benelux
openwrt
firewall
fw4
nftables
blackout
recovery
alex-bot
closed critical

Бенелюкс — после blackout вся LAN без интернета: fw4 не строит forward chain

Симптомы (поверхностные)

  • Александр пожаловался: «после отключения электричества интернет не работает»
  • В unifi.ui.com UniFi-консоль (UCK G2 Plus Benelyuks, 192.168.1.199) показана Offline с прошлого дня — у неё часы отстали почти на 19 часов (NTP не достучался)
  • Mac, телефоны, IoT — Wi-Fi видят, IP получают, но «без интернета»
  • При этом сам Cudy роутер (100.70.207.97 через NetBird) полноценно работает, ping 8.8.8.8 от него = 0% loss

Корневая причина

После blackout-перезагрузки Cudy пакет firewall4 (v2024.12.18, OpenWrt 24.10.3) не смог собрать ruleset, потому что новый nftables v1.1.1 отказался парсить старый синтаксис в /etc/nftables.d/*.nft:

chain dstnat {       # ← UNEXPECTED '{', expecting string or last
  iifname "wt0" tcp dport ... dnat ip to ...
}
chain printer_dnat_pre {       # ← Chain of type "nat" is not supported
  type nat hook prerouting priority dstnat; policy accept;
  ...
}

Файлы, написанные раньше, использовали chain-with-type-hook или add-rules-to-existing-chain-via-blockоба синтаксиса в v1.1.1 либо не поддерживаются вообще, либо требуют точное соответствие имени уже существующего chain в table inet fw4.

Поскольку парсер падал на каждом из этих файлов, fw4 откатывался и не создавал forward и dstnat chains вообще → весь LAN-форвардинг через NAT отсутствовал → ни одно устройство в 192.168.1.0/24 не могло выйти наружу. UCK не достукался до облака Ubiquiti → UI cloud = Offline. Параллельно с этим её время отстало (NTP UDP/123 режется провайдером «Умные сети») — это две независимые проблемы.

Что сделал в восстановлении

  1. Поставил время UCK вручную через SSH (date -u -s "..."; hwclock -w)
  2. Диагностика nft: ядро (nft_chain_nat, nf_nat, nft_ct) и userspace (v1.1.1) на месте, ручные команды через arg работают, но nft -f file со стандартным fw4-output падает на пользовательских includes
  3. Случайно усугубил: opkg install --force-reinstall firewall4 без opkg update — opkg сначала удалил пакет, потом не смог скачать (репозиторий блокировался). fw4 исчез. Скачал .ipk с Mac → scp -O (legacy режим, потому что Cudy без sftp-server) → opkg install /tmp/firewall4.ipk
  4. Отключил все user-.nft-файлы (mv → .disabled-20260605-syntax), оставил только 10-custom-filter-chains.nft (дефолтный шаблон от пакета) → fw4 reload поднял базовый ruleset с forward/dstnat/srcnat chains → LAN-форвардинг заработал
  5. Подкоп: создал зону awg через UCI (uci add firewall zone + device='awg0' + masq=1 + forwarding lan → awg) → подкоп заработал (api.telegram.org HTTP 302 за 0.27s)
  6. Удалил принтер-файлы окончательно (Олег сказал не нужны)

Что временно отключено (.disabled-20260605-syntax)

Файл Назначение Что внутри
00-emergency-block.nft input drop SSH с WAN Дубликат wan-zone drop, не критично
51-awg0-masq.nft masquerade awg0 для LAN Заменено UCI-зоной awg (см. выше)
99-incident-20260520.nft output drop SMTP/SSH + forward drop SSH Бот Алекс alex-secwatch.sh через nft insert rule восстановит SSH-блок каждые 15 мин; SMTP-output на роутере и так не нужен

Что узнал про бота Алекса

Подозревал что бот деплоит битые .nft файлы → проверил. Бот невиновен, его архитектура правильная:

  • /opt/assistant/alex-secwatch.sh (крон */15) использует nft insert rule inet fw4 input iifname "eth0" tcp dport 22 counter drop comment "..." — это runtime-вставка через arg-синтаксис, который поддерживается в nft v1.1.1
  • Никаких записей в /etc/nftables.d/ бот не делает
  • Битые .nft файлы создал я (Claude) в предыдущих сессиях, не бот

Правило на будущее: как добавлять firewall-правила на Бенелюксе (и любом OpenWrt 24.10+)

Цель Как делать Что НЕ делать
Persistent через ребут UCI: uci add firewall rule/redirect/zone/forwarding, потом uci commit firewall; fw4 reload НЕ писать /etc/nftables.d/*.nft с chain xxx { type ... hook ... } или с chain xxx { ... } блоком
Runtime, временно nft insert rule inet fw4 <chain> <expression> через SSH (как делает бот Алекс)
DNAT (port forward) uci add firewall redirect; uci set firewall.@redirect[-1].target='DNAT'; uci set ...src_dport ...dest_ip ...dest_port; uci commit; fw4 reload НЕ писать вручную chain printer_dnat_pre { type nat hook prerouting ... }
Masquerade-зона для нового интерфейса (awg0, wt0 и др.) uci add firewall zone; uci set ...device='awg0' masq='1'; uci add firewall forwarding; uci set ...src=lan dest=awg; uci commit; fw4 reload

Открытое для бота Алекса

Если в будущем бот должен деплоить какие-то правила (например автоматический проброс принтера или DNAT для нового сервиса):

  • использовать uci add firewall redirect ... через SSH к Cudy (persistent),
  • или nft insert rule (временно, как уже делается для SSH-блока).

Никогда не писать в /etc/nftables.d/*.nft с chain xxx { ... } синтаксисом — оно работало на старом nft (v1.0.x), но в v1.1.1 OpenWrt 24.10.3 ломает весь fw4.

TODO

  • При следующем доступе на Cudy — перепроверить что alex-secwatch.sh через nft insert восстановил SSH-WAN-блок (должно произойти через 15 мин от 09:30 UTC)
  • Долгосрочный фикс времени UCK: включить ntpd-сервер на Cudy (uci set system.ntp.enable_server=1) и в UI UCK Network → System → NTP прописать 192.168.1.1 (см. ../projects/benilux/credentials#известная-проблема-ntp-не-работает)
  • Удалить файлы *.disabled-20260605-syntax с роутера через 1-2 недели когда подтвердим что ничего не сломалось