From 0d51b2617010aded49885944724e4b5b23b56bc2 Mon Sep 17 00:00:00 2001 From: Debian Date: Sun, 10 May 2026 21:37:53 +0200 Subject: [PATCH] feat(haproxy): Admin-UI auf eigenem Port :3443 (mailgateway-Pattern) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * HAProxy neues Frontend mgmt_https :3443 → api_backend (Mgmt-UI). Selbe TLS-Cert-Strecke wie :443 (gleicher /etc/edgeguard/tls/-Pool). * :443 verliert default_backend → unbekannte Hosts kriegen 503, nicht mehr versehentlich die Admin-UI. Plus default-Route auf primary_backend pro Domain (catch-all-Routing dort, wo gewollt). * Anti-Lockout in nft-Template um tcp dport 3443 erweitert (zusätzlich zu 22 + 443). * SystemRulesCard zeigt 3443 als 3. Anti-Lockout-Eintrag. Erreichbarkeit: * Public Backends: https://:443 (mit eigenem Cert oder LE) * Admin-UI: https://:3443 (jeder Hostname, default_backend) * SSH: :22 (rate-limited 10/min) Version 1.0.13. 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/firewall/ruleset.nft.tpl | 5 +++-- internal/haproxy/haproxy.cfg.tpl | 18 +++++++++++++++++- management-ui/package.json | 2 +- .../src/components/Layout/Sidebar.tsx | 2 +- .../src/pages/Firewall/SystemRules.tsx | 3 ++- 9 files changed, 28 insertions(+), 10 deletions(-) diff --git a/VERSION b/VERSION index bb83058..2ac9634 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.12 +1.0.13 diff --git a/cmd/edgeguard-api/main.go b/cmd/edgeguard-api/main.go index 781180d..12e6f58 100644 --- a/cmd/edgeguard-api/main.go +++ b/cmd/edgeguard-api/main.go @@ -39,7 +39,7 @@ import ( wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard" ) -var version = "1.0.12" +var version = "1.0.13" func main() { addr := os.Getenv("EDGEGUARD_API_ADDR") diff --git a/cmd/edgeguard-ctl/main.go b/cmd/edgeguard-ctl/main.go index 4351e79..5c0d16f 100644 --- a/cmd/edgeguard-ctl/main.go +++ b/cmd/edgeguard-ctl/main.go @@ -9,7 +9,7 @@ import ( "os" ) -var version = "1.0.12" +var version = "1.0.13" const usage = `edgeguard-ctl — EdgeGuard CLI diff --git a/cmd/edgeguard-scheduler/main.go b/cmd/edgeguard-scheduler/main.go index 003ad44..7224a7c 100644 --- a/cmd/edgeguard-scheduler/main.go +++ b/cmd/edgeguard-scheduler/main.go @@ -5,7 +5,7 @@ import ( "time" ) -var version = "1.0.12" +var version = "1.0.13" func main() { log.Printf("edgeguard-scheduler %s starting", version) diff --git a/internal/firewall/ruleset.nft.tpl b/internal/firewall/ruleset.nft.tpl index d5fd5ab..482494c 100644 --- a/internal/firewall/ruleset.nft.tpl +++ b/internal/firewall/ruleset.nft.tpl @@ -27,8 +27,9 @@ table inet edgeguard { # Diese Block kommt VOR den Custom-Rules — d.h. selbst wenn ein # Operator versehentlich „drop alles" baut, bleibt SSH + Admin-UI # erreichbar. - tcp dport 22 ct state new limit rate 10/minute accept comment "anti-lockout: SSH (rate-limited)" - tcp dport 443 accept comment "anti-lockout: Management-UI (HAProxy/HTTPS)" + tcp dport 22 ct state new limit rate 10/minute accept comment "anti-lockout: SSH (rate-limited)" + tcp dport 443 accept comment "anti-lockout: HAProxy public HTTPS" + tcp dport 3443 accept comment "anti-lockout: Management-UI (HAProxy admin HTTPS)" # Stateful baseline ct state established,related accept diff --git a/internal/haproxy/haproxy.cfg.tpl b/internal/haproxy/haproxy.cfg.tpl index 1111f07..321503a 100644 --- a/internal/haproxy/haproxy.cfg.tpl +++ b/internal/haproxy/haproxy.cfg.tpl @@ -36,10 +36,15 @@ frontend public_http use_backend api_backend if is_acme -# ── Public :443 ──────────────────────────────────────────────────────── +# ── Public :443 (Customer-Backends only) ────────────────────────────── # TLS termination. Reads certs from /etc/edgeguard/tls/ — postinst # seeds a self-signed _default.pem so HAProxy starts before certbot # has issued anything. +# +# WICHTIG: kein default_backend → unbekannte Hosts kriegen 503. Die +# Management-UI sitzt bewusst auf :3443 (siehe mgmt_https unten), +# damit ein versehentlich offengelassenes Wildcard-DNS nie auf das +# Admin-Panel fällt. mailgateway/enconf-Pattern. frontend public_https bind :443 ssl crt /etc/edgeguard/tls/ alpn h2,http/1.1 @@ -49,8 +54,19 @@ frontend public_https {{- range $r := $d.Routes}} use_backend eg_backend_{{$r.BackendID}} if { hdr(host) -i {{$d.Name}} } { path_beg {{$r.PathPrefix}} } {{- end}} + {{- if $d.PrimaryBackendID}} + use_backend eg_backend_{{$d.PrimaryBackendID}} if { hdr(host) -i {{$d.Name}} } + {{- end}} {{- end}} +# ── Mgmt :3443 (Admin-UI only) ──────────────────────────────────────── +# Eigener Port für die Management-UI — gleicher Cert-Pool, aber kein +# Customer-Routing. Anti-Lockout-Regel im nft-Template lässt 3443 +# immer durch. Erreichbar über jede Domain die auf die Box zeigt +# (Hostname egal — default_backend), inkl. der direkten IP. +frontend mgmt_https + bind :3443 ssl crt /etc/edgeguard/tls/ alpn h2,http/1.1 + http-response set-header Strict-Transport-Security "max-age=31536000" default_backend api_backend # ── Internal stats ───────────────────────────────────────────────────── diff --git a/management-ui/package.json b/management-ui/package.json index 9b903bb..150a643 100644 --- a/management-ui/package.json +++ b/management-ui/package.json @@ -1,7 +1,7 @@ { "name": "edgeguard-management-ui", "private": true, - "version": "1.0.12", + "version": "1.0.13", "type": "module", "scripts": { "dev": "vite", diff --git a/management-ui/src/components/Layout/Sidebar.tsx b/management-ui/src/components/Layout/Sidebar.tsx index ffa074c..10c5376 100644 --- a/management-ui/src/components/Layout/Sidebar.tsx +++ b/management-ui/src/components/Layout/Sidebar.tsx @@ -70,7 +70,7 @@ const NAV: NavSection[] = [ }, ] -const VERSION = '1.0.12' +const VERSION = '1.0.13' export default function Sidebar({ isOpen, onClose }: SidebarProps) { const { t } = useTranslation() diff --git a/management-ui/src/pages/Firewall/SystemRules.tsx b/management-ui/src/pages/Firewall/SystemRules.tsx index bd4f741..a85e1b7 100644 --- a/management-ui/src/pages/Firewall/SystemRules.tsx +++ b/management-ui/src/pages/Firewall/SystemRules.tsx @@ -20,7 +20,8 @@ interface SystemRule { const ROWS: SystemRule[] = [ { key: 'a1', chain: 'input', match: 'tcp dport 22 (rate-limit 10/min)', action: 'accept', note: 'anti-lockout: SSH' }, - { key: 'a2', chain: 'input', match: 'tcp dport 443', action: 'accept', note: 'anti-lockout: Management-UI' }, + { key: 'a2', chain: 'input', match: 'tcp dport 443', action: 'accept', note: 'anti-lockout: HAProxy public HTTPS' }, + { key: 'a3', chain: 'input', match: 'tcp dport 3443', action: 'accept', note: 'anti-lockout: Management-UI (admin HTTPS)' }, { key: 'b1', chain: 'input', match: 'ct state established,related', action: 'accept', note: 'stateful baseline' }, { key: 'b2', chain: 'input', match: 'ct state invalid', action: 'drop', note: 'stateful baseline' }, { key: 'b3', chain: 'input', match: 'iif lo', action: 'accept', note: 'loopback' },