export declare const TRUST_PROXY_ENV = "SHORTLINKS_TRUST_PROXY"; export declare const TRUSTED_PROXIES_ENV = "SHORTLINKS_TRUSTED_PROXIES"; /** Reject anything that is not a bare IP literal (optionally bracketed / ported). */ export declare function normalizeIpLiteral(raw: string | null | undefined): string | null; /** Parse and validate `X-Forwarded-For` into bare IP literals, left -> right. */ export declare function parseForwardedFor(header: string | null | undefined): string[]; /** Parse the trusted-proxy allowlist: bare IPs and CIDR blocks (v4 + v6). */ export declare function parseTrustedProxies(raw: string | null | undefined): string[]; /** True when `ip` is one of the trusted proxies, exactly or inside a CIDR. */ export declare function isTrustedAddress(ip: string | null | undefined, trusted: readonly string[]): boolean; export declare const TRUST_TRUE_VALUES: Set; /** Operator opt-in: true only when this service sits behind trusted proxies. */ export declare function resolveTrustProxy(env?: NodeJS.ProcessEnv): boolean; /** Trusted proxy addresses/CIDRs configured by the operator (validated). */ export declare function trustedProxiesFromEnv(env?: NodeJS.ProcessEnv): string[]; export interface RequestClientIpInput { headers: Headers; /** Socket peer address, e.g. `server.requestIP(req)?.address`. */ socketAddress?: string | null; trustProxy?: boolean; /** Validated entries from `parseTrustedProxies`. */ trustedProxies?: readonly string[]; } /** * Resolve the address rate-limit buckets and audit rows are keyed on. * * Trust is OFF by default: forwarding headers are ignored entirely and the * socket peer address is used, so local/dev behavior is unchanged and a * spoofed `x-forwarded-for` can never mint fresh buckets. * * With trust ON the rule is: validated `x-real-ip` (the gateway overwrites it * with the true client IP; direct spoofing is moot because the socket peer is * itself a trusted proxy) -> first untrusted entry of `x-forwarded-for` * counted from the RIGHT (skipping trusted proxies) -> socket peer. Any entry * that is not a bare IP literal is dropped; a header that yields nothing falls * back to the socket peer, which no header can forge. */ export declare function resolveRequestClientIp(input: RequestClientIpInput): string | null;