From 66187e5b77dce78f5c526af87c8c2f728834f649 Mon Sep 17 00:00:00 2001 From: Debian Date: Tue, 12 May 2026 21:14:43 +0200 Subject: [PATCH] =?UTF-8?q?feat(firewall-log):=20Phase=203=20=E2=80=94=20U?= =?UTF-8?q?I=20/firewall-live=20mit=20WS-Stream=20+=20Filter=20+=20CSV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- VERSION | 2 +- cmd/edgeguard-api/main.go | 2 +- cmd/edgeguard-ctl/main.go | 2 +- cmd/edgeguard-scheduler/main.go | 2 +- internal/haproxy/haproxy.cfg.tpl | 4 + management-ui/src/App.tsx | 2 + .../src/components/Layout/AppLayout.tsx | 1 + .../src/components/Layout/Sidebar.tsx | 4 +- management-ui/src/i18n/locales/de/common.json | 35 ++ management-ui/src/i18n/locales/en/common.json | 35 ++ .../src/pages/FirewallLive/index.tsx | 379 ++++++++++++++++++ 11 files changed, 463 insertions(+), 5 deletions(-) create mode 100644 management-ui/src/pages/FirewallLive/index.tsx diff --git a/VERSION b/VERSION index 4bf1778..9972f12 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.60 +1.0.61 diff --git a/cmd/edgeguard-api/main.go b/cmd/edgeguard-api/main.go index 53f5ec7..4865c7d 100644 --- a/cmd/edgeguard-api/main.go +++ b/cmd/edgeguard-api/main.go @@ -49,7 +49,7 @@ import ( wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard" ) -var version = "1.0.60" +var version = "1.0.61" func main() { addr := os.Getenv("EDGEGUARD_API_ADDR") diff --git a/cmd/edgeguard-ctl/main.go b/cmd/edgeguard-ctl/main.go index ff19009..cc3d513 100644 --- a/cmd/edgeguard-ctl/main.go +++ b/cmd/edgeguard-ctl/main.go @@ -9,7 +9,7 @@ import ( "os" ) -var version = "1.0.60" +var version = "1.0.61" const usage = `edgeguard-ctl — EdgeGuard CLI diff --git a/cmd/edgeguard-scheduler/main.go b/cmd/edgeguard-scheduler/main.go index 5ed7088..4fdded2 100644 --- a/cmd/edgeguard-scheduler/main.go +++ b/cmd/edgeguard-scheduler/main.go @@ -24,7 +24,7 @@ import ( "git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts" ) -var version = "1.0.60" +var version = "1.0.61" const ( // renewTickInterval — how often we re-evaluate expiring certs. diff --git a/internal/haproxy/haproxy.cfg.tpl b/internal/haproxy/haproxy.cfg.tpl index 09ded16..9e171df 100644 --- a/internal/haproxy/haproxy.cfg.tpl +++ b/internal/haproxy/haproxy.cfg.tpl @@ -83,7 +83,11 @@ frontend internal_stats # ── Backends ─────────────────────────────────────────────────────────── # edgeguard-api itself: management UI, REST API, ACME webroot. +# timeout tunnel 1h: /api/v1/firewall/log/live ist ein langlebiger +# WebSocket-Stream — ohne Tunnel-Override fällt er nach `timeout +# server 60s` ohne Events um. backend api_backend + timeout tunnel 1h server api1 127.0.0.1:9443 check {{- range $b := .Backends}} diff --git a/management-ui/src/App.tsx b/management-ui/src/App.tsx index cda871f..db06898 100644 --- a/management-ui/src/App.tsx +++ b/management-ui/src/App.tsx @@ -25,6 +25,7 @@ const ForwardProxyPage = lazy(() => import('./pages/ForwardProxy')) const DNSPage = lazy(() => import('./pages/DNS')) const NTPPage = lazy(() => import('./pages/NTP')) const ClusterPage = lazy(() => import('./pages/Cluster')) +const FirewallLivePage = lazy(() => import('./pages/FirewallLive')) const LicensePage = lazy(() => import('./pages/License')) const SettingsPage = lazy(() => import('./pages/Settings')) @@ -109,6 +110,7 @@ export default function App() { } /> } /> } /> + } /> } /> } /> diff --git a/management-ui/src/components/Layout/AppLayout.tsx b/management-ui/src/components/Layout/AppLayout.tsx index 6ceb690..648d714 100644 --- a/management-ui/src/components/Layout/AppLayout.tsx +++ b/management-ui/src/components/Layout/AppLayout.tsx @@ -16,6 +16,7 @@ const PAGE_TITLES: Record = { '/routing-rules': 'nav.routing', '/networks': 'nav.networks', '/ip-addresses': 'nav.ipAddresses', + '/firewall-live': 'nav.firewallLive', '/cluster': 'nav.cluster', '/license': 'nav.license', '/settings': 'nav.settings', diff --git a/management-ui/src/components/Layout/Sidebar.tsx b/management-ui/src/components/Layout/Sidebar.tsx index b7c7798..9c86364 100644 --- a/management-ui/src/components/Layout/Sidebar.tsx +++ b/management-ui/src/components/Layout/Sidebar.tsx @@ -7,6 +7,7 @@ import { ClusterOutlined, CrownOutlined, DashboardOutlined, + EyeOutlined, DatabaseOutlined, FireOutlined, GlobalOutlined, @@ -61,6 +62,7 @@ const NAV: NavSection[] = [ labelKey: 'nav.section.security', items: [ { path: '/firewall', labelKey: 'nav.firewall', icon: }, + { path: '/firewall-live', labelKey: 'nav.firewallLive', icon: }, { path: '/vpn/wireguard', labelKey: 'nav.wireguard', icon: }, { path: '/forward-proxy', labelKey: 'nav.forwardProxy', icon: }, ], @@ -75,7 +77,7 @@ const NAV: NavSection[] = [ }, ] -const VERSION = '1.0.60' +const VERSION = '1.0.61' // Sidebar-Pattern 1:1 aus netcell-webpanel (enconf) übernommen: // -