feat(haproxy): X-Forwarded-Proto + X-Real-IP an alle Backends weiterleiten

User-Frage: „Werden via haproxy die echten IPs durchgereicht?". Antwort:
X-Forwarded-For ja (option forwardfor), aber Apps wie WordPress/Mailcow
brauchen zusätzlich X-Forwarded-Proto=https um Redirect-Loops zu
vermeiden, und X-Real-IP ist die bequeme single-value-Variante die viele
Tools out-of-the-box lesen (ohne die XFF-Chain parsen zu müssen).

Beide Frontends (public_https + mgmt_https) emittieren jetzt:
  http-request set-header X-Forwarded-Proto https
  http-request set-header X-Real-IP %[src]

Was Backends sehen:
  X-Forwarded-For:  <client-ip>             (defaults: option forwardfor)
  X-Forwarded-Proto: https                  (NEW)
  X-Real-IP:        <client-ip>             (NEW, single value)

PROXY-Protocol-Toggle pro Backend kommt nicht in diesem Release — der
Operator hat „nur Header-Variante" gewählt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-13 19:28:41 +02:00
parent a2d08eaa47
commit 3178e25e78
7 changed files with 20 additions and 5 deletions

View File

@@ -1 +1 @@
1.0.77
1.0.78

View File

@@ -54,7 +54,7 @@ import (
wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard"
)
var version = "1.0.77"
var version = "1.0.78"
func main() {
addr := os.Getenv("EDGEGUARD_API_ADDR")

View File

@@ -11,7 +11,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
)
var version = "1.0.77"
var version = "1.0.78"
const usage = `edgeguard-ctl — EdgeGuard CLI

View File

@@ -32,7 +32,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
)
var version = "1.0.77"
var version = "1.0.78"
const (
// renewTickInterval — how often we re-evaluate expiring certs.

View File

@@ -53,6 +53,13 @@ frontend public_https
http-response set-header Strict-Transport-Security "max-age=31536000"
# Client-IP-Weiterleitung an Backends. `option forwardfor` (defaults)
# setzt X-Forwarded-For; wir ergänzen Proto + RealIP damit Apps
# erkennen können (a) dass der Client HTTPS sprach und (b) die
# echte Source-IP ohne XFF-Chain-Parsing brauchen.
http-request set-header X-Forwarded-Proto https
http-request set-header X-Real-IP %[src]
{{- range $d := .Domains}}
{{- range $r := $d.Routes}}
use_backend eg_backend_{{$r.BackendID}} if { hdr(host) -i {{$d.Name}} } { path_beg {{$r.PathPrefix}} }
@@ -70,6 +77,8 @@ frontend public_https
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"
http-request set-header X-Forwarded-Proto https
http-request set-header X-Real-IP %[src]
default_backend api_backend
# ── Internal stats ─────────────────────────────────────────────────────

View File

@@ -43,6 +43,12 @@ func TestRender_BaselineHasFrontendsAndApiBackend(t *testing.T) {
"bind :443 ssl crt /etc/edgeguard/tls/",
"path_beg /.well-known/acme-challenge/",
"http-request redirect scheme https",
// Client-IP-Weiterleitung an Backends — XFF kommt aus
// defaults (option forwardfor), Proto + RealIP setzen wir
// pro public-Frontend explizit.
"option forwardfor",
"http-request set-header X-Forwarded-Proto https",
"http-request set-header X-Real-IP %[src]",
} {
if !strings.Contains(out, w) {
t.Errorf("missing %q in baseline output:\n%s", w, out)

View File

@@ -85,7 +85,7 @@ const NAV: NavSection[] = [
},
]
const VERSION = '1.0.77'
const VERSION = '1.0.78'
// Sidebar-Pattern 1:1 aus netcell-webpanel (enconf) übernommen:
// - <nav> als root, dunkler Gradient + Teal/Blue-Accent