feat(gateway): temporary IP ban (fail2ban) + honeypot/honeytoken (PRERELEASE AG) #97
Reference in New Issue
Block a user
Delete Branch "feature/abuse-ip-ban-honeypot"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Prod-only, in-memory temporary IP ban (fail2ban-style) enforced at the gateway edge, fed by three signals:
noteRateLimitedchoke point./.env,/.git,/wp-*, …) withX-Scrabble-Honeypotand routes them to the gateway; the decoy list is a single source of truth in the Caddyfile.GATEWAY_HONEYTOKEN) compared constant-time inresolve.A banned IP is refused with 429 by the
abuseGuardmiddleware (inside h2c, above the mux) before any work — covering the Connect edge, the live stream and the static SPA/landing the per-op limiter never gated (closes the R3 gap).Off by default (
GATEWAY_ABUSE_BAN_ENABLED=false): the ban keys by the real client IP, which the shared-NAT test contour does not expose, so a ban there would be self-inflicted. Detection (honeypot/honeytoken) still logs in the contour — only the ban action is gated.Operator control
Operators see and lift active bans on the admin console Throttled page (new Active IP bans panel + Unban). The gateway syncs its active set to the backend every 30 s (
POST /api/v1/internal/bans/sync, newbackend/internal/banview) and applies the operator unbans the response returns (≤30 s latency).Out of scope (explicit)
Volumetric L3/L4 DDoS (upstream/CDN), ban persistence (in-memory like
ratewatch), an active-bans Grafana gauge (trimmed — the console view +gateway_abuse_banned_totalcounter cover it).Verification
go build/go vet/gofmt -lclean across gateway + backend;-tags=integrationtype-checks.ratelimit(banlist threshold/expiry/unban/disabled/sweep),connectsrv(abuseGuard 429, honeypot 404+ban, disabled passthrough, honeytoken, public-strike bans / user-class does not),config,backendclient(SyncBans),banview.docker compose configvalidates with the new gateway env.Docs baked in the same PR:
ARCHITECTURE§11/§12,FUNCTIONAL(+ru), both READMEs,PRERELEASE(phase AG).Add a prod-only, in-memory IP ban enforced at the edge, fed by three signals: sustained rate-limiter rejections (the IP-keyed public/email/admin classes — the user class stays the backend soft-flag's concern), a honeypot decoy-path hit (the contour caddy tags decoys with X-Scrabble-Honeypot and routes them to the gateway), and a honeytoken (a planted bearer, GATEWAY_HONEYTOKEN). A banned IP is refused with 429 by the abuseGuard middleware before any work — covering the Connect edge, the live stream and the static SPA/landing the per-op limiter never gated. The ban is off by default: it keys by the real client IP the shared-NAT test contour does not expose, so a ban there would be self-inflicted; detection still logs in the contour, only the ban action is gated (GATEWAY_ABUSE_BAN_ENABLED). Rejection bans last GATEWAY_ABUSE_BAN_DURATION; tripwire/honeytoken hits are near-zero-false-positive and earn longer fixed bans. Each ban increments gateway_abuse_banned_total{reason}. Operators see and lift active bans on the admin console's Throttled page; the gateway syncs its active set to the backend every 30s (POST /api/v1/internal/bans/sync, backend/internal/banview) and applies the operator unbans the response returns. PRERELEASE phase AG. Docs baked into ARCHITECTURE / FUNCTIONAL (+ru) / both READMEs.