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

83 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
date: 2026-06-05
type: decision
tags: [benelux, openwrt, firewall, fw4, nftables, blackout, recovery, alex-bot]
status: closed
severity: 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`**:
```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 недели когда подтвердим что ничего не сломалось