Make the forwarded client-IP header an explicit per-listener choice #73
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Part 1 of #64, split out because it needs a design decision rather than a patch. Not started, no milestone.
access::effective_client_iphonoursCF-Connecting-IPand falls back toX-Real-IPon atrust_forwarded_forlistener. That priority order is only sound if the trusted intermediary overwrites or strips whichever header it does not set. Cloudflare and cloudflared setCF-Connecting-IP, which wins, so the documented deployment is correct — but the README presents nginx, HAProxy and NLB front-ends as supported, and nginx does not setX-Real-IPunless configured to. An operator with HAProxy in front, a trusting listener andallow_ips = ["100.64.0.0/10"]is then bypassed by a client sendingX-Real-IP: 100.64.0.1.#64's own conclusion is the right one and worth preserving: "which header carries the client IP" is a property of the intermediary, and guessing a priority order is what created this. So the fix is an explicit per-listener declaration rather than a documentation note — something like
client_ip_header = "cf-connecting-ip"on the listener, with no fallback, and every other candidate name dropped from the request asCLIENT_CONTROLLED_TRUST_HEADERSalready does.Decisions it needs:
trust_forwarded_for = truelistener, which is the shipped example config among others. Defaulting to today's order keeps the hazard for anyone who does not set it.X-Forwarded-For? It is handled separately and chained, and its leftmost-vs-rightmost question is the same class of ambiguity.Nothing in the fleet is exposed: no deployment puts nginx or HAProxy in front of Edge Router with a trusting listener. Worth doing before one does.
Also from #64, not done and why
A startup warning for
trust_forwarded_for = truewith nomatch_local_ipwas the other suggestion. Not built, because it would fire on the recommended configuration:edge-router.example.toml'scloudflarelistener is exactly that shape, and its own comment explains why it is sound — the parent binding is0.0.0.0:8443inside Docker and never published to the host. Edge Router cannot distinguish that from0.0.0.0on a host NIC, so the warning would cry wolf on the shipped example and be tuned out. If this issue lands, the explicit header declaration makes the dangerous shape detectable properly: a trusting listener that has not declared which header it trusts.