Skip to content

qrest: resolve client IP from X-Forwarded-For behind trusted proxies - #392

Merged
ar merged 1 commit into
mainfrom
feat/qrest-trusted-proxies
Aug 12, 2026
Merged

qrest: resolve client IP from X-Forwarded-For behind trusted proxies#392
ar merged 1 commit into
mainfrom
feat/qrest-trusted-proxies

Conversation

@ar

@ar ar commented Aug 12, 2026

Copy link
Copy Markdown
Member

The qrest-access log records the socket peer, which behind a reverse proxy (Traefik, nginx, an ingress controller) is the proxy — the real caller's address is lost.

This adds an optional trusted-proxy-cidrs property to the qrest QBean (comma-separated CIDRs, e.g. 10.42.0.0/16, 127.0.0.1/32). When set and the socket peer falls inside a trusted CIDR, the logged remote becomes the rightmost X-Forwarded-For entry not itself in the trusted set — i.e. the client as witnessed by the outermost trusted proxy.

Security properties, all covered by tests:

  • Forwarded headers from an untrusted peer are never believed, so a direct caller cannot forge its logged identity with a crafted header (RestSessionTest.forwardedHeaderFromUntrustedPeerIsIgnored).
  • Client-forged prefix entries in the chain are ignored; the entry appended by the trusted proxy wins.
  • An all-trusted chain yields its leftmost entry (originator inside the trusted network); missing/garbage headers fall back to the socket peer.
  • Address literals only — no DNS lookups; IPv6 (bracketed, CIDR) and IPv4:port forms normalized.
  • A malformed CIDR throws at configuration time: a typo must fail deployment loudly, not silently trust the wrong network.

Unset property = previous behavior, byte for byte. :modules:qrest:test and javadoc green.

Behind a reverse proxy (Traefik, nginx, an ingress controller) the
qrest-access log records the proxy's socket address, losing the real
caller. A new optional trusted-proxy-cidrs property on the qrest QBean
(comma-separated CIDRs) fixes that: when the socket peer is inside a
trusted CIDR, the logged remote becomes the rightmost X-Forwarded-For
entry not itself in the trusted set — the client as witnessed by the
outermost trusted proxy.

Forwarded headers from any other peer are never believed (a direct
caller cannot forge its logged identity), an all-trusted chain yields
its leftmost entry, a missing/garbage header falls back to the socket
peer, and a malformed CIDR fails deployment loudly instead of silently
trusting the wrong network. Unset property = previous behavior,
byte for byte.
@ar
ar merged commit 9ffc664 into main Aug 12, 2026
1 check passed
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