Rate Limiting & DoS Protection
En bref
Multi-dimensional rate limiting and DoS protection layered across every API surface: per-IP, per-user and per-tenant sliding windows enforced in middleware, Cloudflare DDoS protection with optional origin lock-down, login brute-force defence with per-IP exponential backoff and Cloudflare Turnstile CAPTCHA fallback, plus adaptive rate limits that contract automatically across three regimes when total platform traffic spikes.
Comment ça fonctionne
Three sliding-window enforcers run inside RateLimitMiddleware on every request. Per-IP enforcement defaults to 200 requests / 60 seconds, per authenticated user 300/60s keyed on principal_id, per tenant 5 000/60s keyed on tenant_id; health-check paths are exempt and the public pseudo-user does not consume the per-user budget. When a limit trips the request returns 429 with Retry-After and X-RateLimit-* response headers so well-behaved clients back off cleanly. The three windows are independent — a single noisy script that exhausts its IP budget cannot drag down its tenant, and an aggressive tenant cannot starve other tenants on the same Container App.
Cloudflare sits in front. CloudflareMiddleware extracts the real client IP from CF-Connecting-IP (so per-IP limits track the actual caller, not Cloudflare's edge), passes through CF-Ray and CF-IPCountry as response headers for traceability, and optionally enforces origin protection — when CLOUDFLARE_REQUIRE_HEADER is set, requests that bypass Cloudflare and hit the origin directly return 403, closing the back door that DDoS floods love to find. An X-Cloudflare-Protected response header lets ops verify the chain is intact.
Login endpoints get a separate LoginProtectionMiddleware. It watches POST /auth/token, /auth/login and friends for HTTP 401/403 responses, applies per-IP exponential backoff (1s → 2s → 4s → ... → 30s capped) and locks out with Retry-After when the budget exhausts. After a configurable failure threshold (default 3) it requires a Cloudflare Turnstile token via X-Captcha-Token before further attempts; the response carries captcha_required: true so the login UI knows to render the widget. Turnstile verification goes through a shared verify_turnstile_token service that the marketing, signup, contract and feature-request flows reuse — a single defense-in-depth layer over honeypot and rate-limit.
The top-level safety net is adaptive. AdaptiveRateLimitController samples total API traffic in a sliding window and dynamically scales the global rate limits across three regimes: normal at 1.0×, elevated at 0.5× when traffic hits 2× baseline, critical at 0.25× at 5× baseline. The middleware reads the current multiplier on every check, so a sudden flood throttles itself before the underlying database notices.
Capacités clés
- Per-IP sliding window (default 200/60s) with 429 + Retry-After + X-RateLimit-* headers
- Per-authenticated-user sliding window (default 300/60s) keyed on principal_id
- Per-tenant sliding window (default 5 000/60s) preventing single-tenant resource monopolisation
- Cloudflare integration extracting real client IP and optionally locking direct-to-origin access
- LoginProtectionMiddleware with per-IP exponential backoff (1s → 30s capped) on auth failures
- Cloudflare Turnstile CAPTCHA fallback after configurable failure threshold (default 3)
- AdaptiveRateLimitController with normal / elevated / critical regimes (1.0× / 0.5× / 0.25×)
- Turnstile bot-protection on all public POST endpoints (auth, marketing, signup, contract, feature-requests)
En pratique
A scraper farms public ranking data with a single misconfigured loop. Cloudflare absorbs the noise at the edge, the per-IP limiter trips on the first 201 requests in under a minute, and the script gets a clean 429 with Retry-After 47. Meanwhile a credential-stuffing attack hits POST /auth/login from a botnet — every attempt fails with 401, LoginProtectionMiddleware kicks each source IP into exponential backoff and after three failures the response demands a Turnstile token.
The bots cannot solve it, the budget exhausts, the lockout holds. On the dashboard ops watches total request volume hit 4× baseline; the adaptive controller kicks in at 0.5× across the board, then settles back to 1.0× ten minutes later as the storm passes — without a single page firing.
Fonctionnalités de ce sous-système
8| ID | Status | Fonctionnalités |
|---|---|---|
| F16.10.01 | Livré | Rate limiting per IP — sliding-window per-IP enforcement via RateLimitMiddleware, configurable limit/window (default 200/60s), 429 response with Retry-After and X-RateLimit-* headers, health-check paths exempt. Implemented (PL-F1610a). ✅ PL-F1610a |
| F16.10.02 | Livré | Rate limiting per user — per-authenticated-user sliding window (default 300/60s), keyed on principal_id from auth context, public pseudo-users excluded, independent from per-IP limits. Implemented (PL-F1610a). ✅ PL-F1610a |
| F16.10.03 | Livré | Rate limiting per tenant — aggregate sliding window across all users within a tenant (default 5000/60s), keyed on tenant_id from auth context, prevents single-tenant resource monopolisation. Implemented (PL-F1610a). ✅ PL-F1610a |
| F16.10.04 | Livré | Cloudflare DDoS-skydd — CloudflareMiddleware extracts real client IP from CF-Connecting-IP, passes through CF-Ray/CF-IPCountry as response headers, optional origin protection (CLOUDFLARE_REQUIRE_HEADER) blocks direct access (403), X-Cloudflare-Protected response header. Implemented (PL-F1610a). ✅ PL-F1610a |
| F16.10.05 | Livré | Brute-force-skydd på login — LoginProtectionMiddleware monitors auth endpoints (POST /auth/token, /auth/login, etc.) for failed login attempts (HTTP 401/403), applies per-IP exponential backoff (1s→2s→4s→...→30s capped), lockout with Retry-After header. Implemented (PL-F1610b). ✅ PL-F1610b |
| F16.10.06 | Livré | CAPTCHA fallback vid attack — after configurable failure threshold (default 3), requires Cloudflare Turnstile CAPTCHA token via X-Captcha-Token header before allowing further login attempts. Returns 429 with captcha_required: true. Shared verify_turnstile_token service. Implemented (PL-F1610b). ✅ PL-F1610b |
| F16.10.07 | Livré | Adaptive rate limits baserat på trafik — AdaptiveRateLimitController monitors total API traffic volume in sliding window, dynamically adjusts rate limits across three levels: normal (1.0×), elevated (0.5× at 2× baseline), critical (0.25× at 5× baseline). Integrated with RateLimitMiddleware. Implemented (PL-F1610b). ✅ PL-F1610b |
| F16.10.08 | Livré | Turnstile bot-protection på alla publika POST-endpoints — TurnstileMiddleware för auth-endpoints + Depends(verify_turnstile) för marketing/signup/contract/feature-requests. Defense-in-depth med honeypot + rate-limit. Shared widget i packages/shared/src/turnstile/. CSP uppdaterad för challenges.cloudflare.com. Fail-open vid CF-timeout (5s). Implemented (PL-T072). ✅ PL-T072 |