feat(firewall-log): Phase 3 — UI /firewall-live mit WS-Stream + Filter + CSV

Neue Page management-ui/src/pages/FirewallLive — Live-Tail der NFLOG-
Events aus /api/v1/firewall/log/live (WebSocket). Features:

- Status-Indicator (Live/getrennt), Auto-Reconnect alle 2s nach Drop
- Filter-Bar (action/proto/src/dst/rule_id) — bei Änderung wird der
  WS neu verbunden, Server schickt frischen Snapshot
- Pause-Toggle: während Pause werden Events gebuffert (max 1000),
  beim Resume in die Tabelle gemerged
- CSV-Export der aktuellen Tabelle (timestamp/rule/action/proto/src/
  dst/iface/size)
- Color-coded Action-Tags (ACCEPT=grün, DROP=rot, REJECT=orange)
- Ring-Buffer 1000 im UI damit die DOM-Last bei Hochlast bleibt
- Sidebar-Eintrag "Firewall-Log" unter Sicherheit (Eye-Icon)
- DE/EN i18n

haproxy: backend api_backend bekommt `timeout tunnel 1h` damit der
WebSocket-Stream nicht nach `timeout server 60s` ohne Events stirbt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-12 21:14:43 +02:00
parent a798d1b796
commit 66187e5b77
11 changed files with 463 additions and 5 deletions

View File

@@ -17,6 +17,7 @@
"dns": "DNS",
"ntp": "Zeit (NTP)",
"firewall": "Firewall",
"firewallLive": "Firewall-Log",
"cluster": "Cluster",
"license": "Lizenz",
"settings": "Einstellungen",
@@ -617,5 +618,39 @@
"verifyFailed": "Lizenz-Verifizierung fehlgeschlagen",
"cta": "Jetzt aktivieren →",
"openPage": "Lizenz-Seite öffnen →"
},
"fwlog": {
"title": "Firewall-Log (Live)",
"intro": "Pakete, die in nft-Regeln mit aktivem Log-Flag matchen, fließen via NFLOG → ulogd2 → JSONL hierher. WebSocket-Stream zeigt Live-Events; Ring-Buffer (1000) hält die letzten Treffer auch nach Reconnect.",
"live": "Live",
"disconnected": "getrennt",
"pause": "Pause",
"resume": "Fortsetzen",
"queued": "wartend",
"clear": "Leeren",
"clearTooltip": "Tabelle leeren (Server-Ringbuffer bleibt unverändert)",
"export": "CSV",
"exportTooltip": "Aktuelle Tabelle als CSV exportieren",
"exportEmpty": "Keine Events zum Exportieren",
"connError": "WebSocket-Fehler — versuche erneut",
"empty": "Noch keine Events. Aktiviere bei einer Firewall-Regel den Log-Schalter, dann fließen Treffer hier hinein.",
"connecting": "Verbinde …",
"col": {
"time": "Zeit",
"action": "Aktion",
"rule": "Rule",
"proto": "Proto",
"src": "Quelle",
"dst": "Ziel",
"iface": "Interface",
"size": "Größe"
},
"filter": {
"action": "Action filtern",
"proto": "Proto filtern",
"src": "Quell-IP",
"dst": "Ziel-IP",
"rule": "Rule-ID"
}
}
}