mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-10-20 22:51:18 +02:00
fix: rate-limit visitors by real IP regardless of Cloudflare proxy hops (#750)
Since the night of 2026-07-16 production keyed the rate limiter on Cloudflare edge IPs instead of visitor IPs: every visitor routed through the same edge shared one 175-req/15min bucket, causing widespread 429s (confirmed by probing: sequential requests alternated 200/429 across fresh and exhausted buckets). Root cause: 'trust proxy' used a fixed hop count (TRUST_PROXY=1), which silently breaks whenever the proxy chain gains or loses an X-Forwarded-For entry (e.g. a Cloudflare-side change). - TRUST_PROXY now accepts a comma-separated subnet list; the new default 'loopback,uniquelocal,cloudflare' expands Cloudflare's published IP ranges so Express skips trusted proxies no matter how many entries they add. Plain numbers keep the legacy hop-count behavior. - If resolution still stops at a Cloudflare address (visitor missing from X-Forwarded-For entirely), the limiter key falls back to cf-connecting-ip — safe because request.ip can only be a Cloudflare address when the whole chain to it is trusted. - CIDR matching uses Node's built-in net.BlockList (no new dependency). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3f2d6d1a64
commit
6a820408a1
5 files changed
+288
-19
No files matched your search
+14
-2
@@ -34,7 +34,15 @@ interface Config {
|
||||
S3_ENDPOINT: string | null;
|
||||
S3_REGION: string | null;
|
||||
STORAGE: "filesystem" | "s3";
|
||||
TRUST_PROXY: number;
|
||||
/**
|
||||
* Value for Express "trust proxy": either a fixed hop count ("1", "2")
|
||||
* or a comma-separated list of trusted subnets — named subnets
|
||||
* ("loopback", "linklocal", "uniquelocal"), IPs/CIDRs, and the keyword
|
||||
* "cloudflare" (expands to Cloudflare's published ranges). The subnet
|
||||
* form keeps request.ip pointing at the real visitor even when the
|
||||
* proxy chain gains or loses hops. See src/server/trustProxy.ts.
|
||||
*/
|
||||
TRUST_PROXY: string;
|
||||
RATE_LIMIT: number;
|
||||
}
|
||||
const config: Config = {
|
||||
@@ -55,7 +63,11 @@ const config: Config = {
|
||||
AUTH_CALLBACK: "http://localhost:5000/github/auth",
|
||||
ANONYMIZATION_MASK: "XXXX",
|
||||
PORT: 5000,
|
||||
TRUST_PROXY: 1,
|
||||
// Trust the local reverse proxy (docker network / host nginx) and
|
||||
// Cloudflare's edges by subnet rather than by hop count, so client-IP
|
||||
// resolution survives Cloudflare adding or removing X-Forwarded-For
|
||||
// entries. Set a plain number to restore the legacy hop-count behavior.
|
||||
TRUST_PROXY: "loopback,uniquelocal,cloudflare",
|
||||
RATE_LIMIT: 350,
|
||||
APP_HOSTNAME: "anonymous.4open.science",
|
||||
DB_USERNAME: "admin",
|
||||
|
||||
Reference in new issue
Block a user