feat(api, web): add Linux nft destination port hits for blocked IPs
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 1m59s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped

Track tcp/udp dports via deny_port_hits, expose aggregate and per-IP ports in UI; install-link re-run refreshes nft rules.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-08-11 00:33:03 +07:00
co-authored by Cursor
parent 402182195f
commit c5069fbdaf
16 changed files with 897 additions and 30 deletions
+16 -2
View File
@@ -20,7 +20,7 @@ curl -fsSL https://<cp>/agent-install/<id> | bash
3. После enroll статус станет **Pending** — одобрите агента (Approve).
4. **Approved** — агент синхронизирует политику.
**Повторный запуск той же install-ссылки** на хосте, где агент уже стоит: обновляет sync-скрипт / timer (или MikroTik scheduler), **без** повторного enroll — `CLIENT_ID`/`token` сохраняются. Полный переустановки с новым токеном: `EVOFW_INSTALL_FORCE=1` (Linux).
**Повторный запуск той же install-ссылки** на хосте, где агент уже стоит: обновляет sync-скрипт / timer (или MikroTik scheduler) **и пересоздаёт nft rules** (в т.ч. `deny_port_hits`), **без** повторного enroll — `CLIENT_ID`/`token` сохраняются. Сбрасывается `last_hash`, затем сразу force sync. Полный переустановки с новым токеном: `EVOFW_INSTALL_FORCE=1` (Linux).
API (auth): `POST /api/v1/install-links` `{ "name": "web-01", "platform": "linux" | "mikrotik" }`.
@@ -58,7 +58,7 @@ Whitelist: nft chain policy drop + allow set. Blacklist: policy accept + deny se
Linux agent reports optional `ip_hits` in `POST /v1/agent/apply-report`:
- **nft:** tries set `deny_v4` with `flags interval; counter;`. If the kernel rejects counters on interval sets, falls back to plain interval (aggregate Traffic ↓ still works; per-IP empty).
- Upgrade path: on install-link re-run, `last_hash` is cleared once so sets can be recreated (chain deleted before set replace).
- Upgrade path: on install-link re-run, `last_hash` is cleared once so sets/chain can be recreated (chain deleted before set replace)**обновляет и port-hit правила**.
- **ipset:** prefers `hash:net … counters` on create; existing sets without counters are left as-is.
- Payload: only entries with `packets > 0`, **top 200** by packets.
- Control plane: `agent_ip_block_stats`, accumulates **deltas** of absolute kernel counters (как Traffic ↓). После flush set/chain (policy apply) CP сбрасывает per-IP baseline (`last_reported`), иначе вторая эпоха счётчиков теряется (Traffic растёт, Blocked IPs — нет).
@@ -67,6 +67,20 @@ Linux agent reports optional `ip_hits` in `POST /v1/agent/apply-report`:
IPv6 skipped.
## Destination ports (Linux nft)
На **nft** агент ведёт dynamic set `deny_port_hits` (`ipv4_addr . inet_proto . inet_service`, timeout 1h, counter):
- Deny rule для tcp/udp: `update @deny_port_hits { ip saddr . meta l4proto . th dport }` + drop; прочие протоколы — plain drop.
- В `apply-report`: optional `port_hits` top **500** `{ ip, port, protocol, packets }`.
- CP: `agent_port_block_stats` (absolute deltas). Set **не** flush’ится на каждый policy apply (элементы живут по timeout) — baseline не сбрасывается при Traffic flush.
- `GET /api/v1/agents/:id/blocked-ports` — aggregate top 50 портов; в `blocked-ips` у каждого IP — `ports` top 5.
- UI: **Top ports** + колонка Ports в Blocked IPs (только `platform=linux`).
- **ipset/iptables:** `port_hits: []`. MikroTik — без port hits.
- Чтобы подтянуть правила на уже установленном агенте: **re-run install one-liner** (см. выше).
IPv6 skipped.
## MikroTik (RouterOS 7.21+)
В UI `/agents`**Добавить агента** → platform **MikroTik**. Скопируйте one-liner: