Skip to content

Resolve the real client IP behind a trusted reverse proxy - #192

Open
williamthome wants to merge 4 commits into
mainfrom
feat/real-ip-resolution
Open

Resolve the real client IP behind a trusted reverse proxy#192
williamthome wants to merge 4 commits into
mainfrom
feat/real-ip-resolution

Conversation

@williamthome

Copy link
Copy Markdown
Member

Description

Behind an HTTP-terminating reverse proxy the socket peer is the proxy, so roadrunner_req:client_ip/1 reports the proxy for every request and the per-peer rate_limit bucket collapses onto a single key. The new real_ip listener option opts into nginx-realip-style resolution: the immediate peer must itself match trusted_proxies before any forwarded header is honored, then the chain is walked right-to-left, skipping trusted proxies, to the first untrusted address. A client that bypasses the proxy has its own header ignored, so it cannot spoof its address. The resolved address feeds both client_ip/1 and the rate-limit key, and composes with proxy_protocol (the PROXY-reported address becomes the immediate hop). CIDRs are pre-compiled at listener init to {Family, NetPrefix, Shift}, so the per-request check is a shift and a compare.

roadrunner:start_listener(api, #{
    port => 8080,
    real_ip => #{trusted_proxies => [~"10.0.0.0/8", ~"::1/128"]},
    rate_limit => #{limit => 100, window => 1000}
}, Routes).

RFC 9110 §5.3 makes repeated field lines equivalent to the single comma-joined value, so a proxy that emits the chain as separate header lines resolves identically to one that combines it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant