feat: umfangreiches UI+API-Polish (v1.1.36–1.1.42)
Backend: - Audit-Log: Search-Endpoint mit ILIKE-Filter (actor/action/subject/date) - NTP: /ntp/status via chronyc tracking (Stratum, Offset, Quelle) - System: /service-restart mit Allowlist (haproxy/squid/unbound/chrony/scheduler) - Domain-Response-Headers + Rate-Limit (Migration 0024) - Join-Tokens (Migration 0025), Cluster-mTLS, Aggregator-Fan-Out - apt-Service für Update-Banner (apt-get update + Versionsprüfung) - Backup-Retry mit exponential backoff (retry_apt 3×) - publish.sh fail-fast + cleanup-old.sh (max 10 Versionen) Frontend: - Audit-Log-Page (/audit) mit Filter + Pagination - ErrorBoundary an React-Root + Vite build-target festgenagelt (iOS 15+) - Storage-Schema-Stamp: auto-wipe bei Versions-Mismatch (blank-page-Fix) - EmptyState-Komponente überall ausgerollt - SSL: Aggregate-Karte (total/expiring/expired/errors) - Backups: Aggregate-Karte (letzter Backup/Größe/Fehlschläge 24h) + Backup-Now - NTP: Sync-Status-Karte (chronyc tracking live) - Domains: Backend-UP/DOWN-Chip aus HAProxy-Stats - Backends: HAProxy-Status-Spalte (UP/DEGRADED/DOWN) - Settings: Service-Neustart-Karte (haproxy/squid/unbound/chrony/scheduler) - Settings: Upgrade-Status-Card, Wartungsmodus, Auto-Update, Retention - Dashboard: Recent-Alerts, Cluster-Health, License-Chip, Onboarding-Hint - System-Regeln im Firewall als eigener Tab Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,11 @@ global
|
||||
daemon
|
||||
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
|
||||
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
||||
# HAProxy 3.0.x in Trixie ist mit USE_QUIC=1 + USE_QUIC_OPENSSL_COMPAT=1
|
||||
# gebaut; die System-OpenSSL kann QUIC aber nur über den Kompat-Layer.
|
||||
# Ohne dieses Flag verweigert HAProxy `bind quic4@…` mit "this SSL
|
||||
# library does not support the QUIC protocol".
|
||||
limited-quic
|
||||
|
||||
defaults
|
||||
log global
|
||||
@@ -50,8 +55,14 @@ frontend public_http
|
||||
# Admin-Panel fällt. mailgateway/enconf-Pattern.
|
||||
frontend public_https
|
||||
bind :443 ssl crt /etc/edgeguard/tls/ alpn h2,http/1.1
|
||||
# HTTP/3 via QUIC (UDP/443). HAProxy 3.0.x ist mit USE_QUIC=1
|
||||
# gebaut; Browser fallen via Alt-Svc-Header (siehe unten) für
|
||||
# Folge-Requests auf h3 zurück.
|
||||
bind quic4@:443 ssl crt /etc/edgeguard/tls/ alpn h3
|
||||
|
||||
http-response set-header Strict-Transport-Security "max-age=31536000"
|
||||
# Alt-Svc: signalisiert dass h3 auf demselben Port verfügbar ist.
|
||||
# ma=86400 = Browser darf den Hinweis 24h cachen.
|
||||
http-response set-header Alt-Svc "h3=\":443\"; ma=86400"
|
||||
|
||||
# Client-IP-Weiterleitung an Backends. `option forwardfor` (defaults)
|
||||
# setzt X-Forwarded-For; wir ergänzen Proto + RealIP damit Apps
|
||||
@@ -60,7 +71,47 @@ frontend public_https
|
||||
http-request set-header X-Forwarded-Proto https
|
||||
http-request set-header X-Real-IP %[src]
|
||||
|
||||
{{- if .GlobalMaintenance}}
|
||||
# Whole-Box-Maintenance — Settings → Maintenance-Mode aktiv. Dieser
|
||||
# Block kommt VOR allen per-Domain ACLs und blockt JEDEN Customer-
|
||||
# Request. Mgmt-UI auf :3443 (mgmt_https) ist davon nicht betroffen.
|
||||
http-request return status 503 content-type "text/plain; charset=utf-8" string "{{.GlobalMaintenanceMessage}}"
|
||||
{{- end}}
|
||||
|
||||
{{- range $d := .Domains}}
|
||||
{{- if $d.RedirectFromHost}}
|
||||
# www-Redirect: {{$d.RedirectFromHost}} → {{$d.Name}}
|
||||
http-request redirect prefix https://{{$d.Name}} code 301 if { hdr(host) -i {{$d.RedirectFromHost}} }
|
||||
{{- end}}
|
||||
{{- if $d.MaintenanceMode}}
|
||||
# Wartungs-Modus für {{$d.Name}} — alle Requests werden mit 503 beantwortet.
|
||||
http-request return status 503 content-type "text/plain; charset=utf-8" string "{{$d.MaintMessage}}" if { hdr(host) -i {{$d.Name}} }
|
||||
{{- end}}
|
||||
{{- if $d.MaxBodyBytes}}
|
||||
# Body-Size-Cap für {{$d.Name}}: {{$d.MaxBodyBytes}} Bytes.
|
||||
# Nur Content-Length wird geprüft — Chunked-Bodies wären erst nach
|
||||
# http-buffer-request abgreifbar, das wollen wir auf Frontend-Level
|
||||
# nicht aktivieren (verbraucht RAM pro Connection).
|
||||
http-request deny deny_status 413 if { hdr(host) -i {{$d.Name}} } { req.hdr_val(content-length) -m int gt {{$d.MaxBodyBytes}} }
|
||||
{{- end}}
|
||||
{{- if $d.RateLimitThreshold}}
|
||||
# Rate-Limit für {{$d.Name}}: {{$d.RateLimitRPS}} req/s pro Client-IP
|
||||
# (Schwelle = rps × 10s-Fenster = {{$d.RateLimitThreshold}} hits).
|
||||
http-request track-sc0 src table rl_{{$d.ID}} if { hdr(host) -i {{$d.Name}} }
|
||||
http-request deny deny_status 429 if { hdr(host) -i {{$d.Name}} } { sc_http_req_rate(0) gt {{$d.RateLimitThreshold}} }
|
||||
{{- end}}
|
||||
{{- if $d.HSTSHeader}}
|
||||
# del + set damit ein vom Backend gesetztes HSTS (z. B. nginx mit
|
||||
# eigener add_header-Direktive) garantiert von unserer Policy
|
||||
# überschrieben wird — sonst tauchen 2 Strict-Transport-Security
|
||||
# Header in der Response auf.
|
||||
http-response del-header Strict-Transport-Security if { hdr(host) -i {{$d.Name}} }
|
||||
http-response set-header Strict-Transport-Security "{{$d.HSTSHeader}}" if { hdr(host) -i {{$d.Name}} }
|
||||
{{- end}}
|
||||
{{- range $h := $d.ResponseHeaders}}
|
||||
http-response del-header {{$h.Name}} if { hdr(host) -i {{$d.Name}} }
|
||||
http-response set-header {{$h.Name}} "{{$h.Value}}" if { hdr(host) -i {{$d.Name}} }
|
||||
{{- end}}
|
||||
{{- range $r := $d.Routes}}
|
||||
use_backend eg_backend_{{$r.BackendID}} if { hdr(host) -i {{$d.Name}} } { path_beg {{$r.PathPrefix}} }
|
||||
{{- end}}
|
||||
@@ -99,6 +150,20 @@ backend api_backend
|
||||
timeout tunnel 1h
|
||||
server api1 127.0.0.1:9443 check
|
||||
|
||||
{{- /* Per-Domain Rate-Limit Stick-Tables.
|
||||
Eigenes Backend pro Domain damit verschiedene Schwellen nicht
|
||||
miteinander interferieren; HAProxy 3.0 erlaubt mehrere
|
||||
stick-table-Backends die per Frontend mit track-sc0 angesteuert
|
||||
werden. expire 10s hält den Speicher knapp. */ -}}
|
||||
{{- range $d := .Domains}}
|
||||
{{- if $d.RateLimitThreshold}}
|
||||
|
||||
backend rl_{{$d.ID}}
|
||||
# Rate-Limit-Counter für {{$d.Name}}; gefüllt von public_https.
|
||||
stick-table type ip size 100k expire 10s store http_req_rate(10s)
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
|
||||
{{- range $b := .Backends}}
|
||||
|
||||
backend eg_backend_{{$b.ID}}
|
||||
|
||||
Reference in New Issue
Block a user