From 570f4f94e41c99a46f2ee5a2c4c3b1d025113aa0 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Mon, 12 Oct 2026 09:55:06 +0200 Subject: [PATCH] fix(security): TRUST_PROXY hinter Cloudflare auf Netzliste statt Hop-Zahl Mit TRUST_PROXY=1 (Standard) war req.ip die Cloudflare-Edge, weil Traefik sie als letzten X-Forwarded-For-Eintrag anhaengt. Rate-Limits trafen damit alle Clients derselben Edge gemeinsam, und IP-Freigaben von API-Schluesseln sahen nie die echte Adresse. Vorlage und .env.example nennen jetzt "loopback, uniquelocal" plus die Cloudflare-Netze: Express nimmt den ersten Eintrag von rechts ausserhalb dieser Netze, also den Client, den Cloudflare angehaengt hat. Vom Client mitgeschickte Eintraege links davon erreicht die Auswertung nie. Co-Authored-By: Claude Opus 5.5 (1M context) --- ApiCore-Backend/.env.example | 3 +++ deploy/k8s/backend/configmap.example.yaml | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/ApiCore-Backend/.env.example b/ApiCore-Backend/.env.example index 74c309b..7bcdebb 100644 --- a/ApiCore-Backend/.env.example +++ b/ApiCore-Backend/.env.example @@ -21,6 +21,9 @@ FRONTEND_ORIGIN="http://localhost:3000" # Reverse-proxy hops in front of the backend whose X-Forwarded-For is # trusted (client IP for rate limits and API-key IP allowlists). "1" for the # single K8s ingress; a list such as "loopback, 10.0.0.0/8" also works. +# Behind Cloudflare + Traefik use "loopback, uniquelocal, " +# (see deploy/k8s/backend/configmap.example.yaml); "1" would yield the +# Cloudflare edge IP that many clients share. TRUST_PROXY=1 # Refresh-token cookie requires HTTPS by default. Set to "false" only for diff --git a/deploy/k8s/backend/configmap.example.yaml b/deploy/k8s/backend/configmap.example.yaml index d6c05b1..b07f266 100644 --- a/deploy/k8s/backend/configmap.example.yaml +++ b/deploy/k8s/backend/configmap.example.yaml @@ -15,6 +15,12 @@ data: BACKUP_CRON_SCHEDULE: "0 3 * * *" BACKUP_RETENTION_COUNT: "14" COOKIE_SECURE: "true" + # Client-IP fuer Rate-Limits und IP-Freigaben der API-Schluessel. Vertraut + # werden Cluster/LAN (Traefik) und Cloudflare (https://www.cloudflare.com/ips/). + # Express nimmt den ersten X-Forwarded-For-Eintrag von rechts, der aus keinem + # dieser Netze kommt: den Client, den Cloudflare angehaengt hat. Mit "1" waere + # es die Cloudflare-Edge, die sich viele Clients teilen. + TRUST_PROXY: "loopback, uniquelocal, 173.245.48.0/20, 103.21.244.0/22, 103.22.200.0/22, 103.31.4.0/22, 141.101.64.0/18, 108.162.192.0/18, 190.93.240.0/20, 188.114.96.0/20, 197.234.240.0/22, 198.41.128.0/17, 162.158.0.0/15, 104.16.0.0/13, 104.24.0.0/14, 172.64.0.0/13, 131.0.72.0/22, 2400:cb00::/32, 2606:4700::/32, 2803:f800::/32, 2405:b500::/32, 2405:8100::/32, 2a06:98c0::/29, 2c0f:f248::/32" # Entra ID SSO. Issuer ist die v2.0-Metadaten-URL des Tenants, # Redirect-URI muss exakt der im App-Registrierung hinterlegten entsprechen. # Ohne diese vier Variablen (siehe secret.example.yaml fuer Client-ID/-Secret)