DanielRamosAcosta opened a new issue, #6052:
URL: https://github.com/apache/couchdb/issues/6052
### Provide a brief overview of what the new feature is all about
The authentication lockout added in 3.4 (`[chttpd_auth_lockout]`) keys its
rate-limit on a `{peer IP, username, salt}` tuple. The peer IP comes from
`mochiweb_request:get(peer, …)`. When CouchDB runs behind a reverse proxy or
CDN, that function returns the **last** entry of `X-Forwarded-For` — the
nearest proxy, not the real client — and there is no way to configure this.
This request asks for a configurable way to determine the client IP (which
header, and/or how many trusted hops) so the lockout counts per real client IP.
### Tell us how the new feature should work. Be specific
Add configuration (e.g. under `[chttpd]`) to control how the client IP is
derived from forwarded headers, mirroring the existing `x_forwarded_host` /
`x_forwarded_proto` / `x_forwarded_ssl` options — which already handle
host/scheme behind a proxy but **not** the client IP. For example, any of:
- a setting to choose the source header (e.g. `X-Forwarded-For`,
`X-Real-IP`, or a CDN-specific header);
- a "trusted hops" count to skip N rightmost entries of `X-Forwarded-For`
(like nginx `real_ip_recursive` or Traefik `ipStrategy.depth`);
- a list of trusted proxy CIDRs whose addresses are stripped, taking the
rightmost *untrusted* address (like nginx `set_real_ip_from`).
The resolved IP would be used both for the lockout key and for request
logging. Default behaviour unchanged for backwards compatibility.
Illustrative example (documentation IPs): with `X-Forwarded-For:
203.0.113.10, 198.51.100.7` (real client, then one proxy), the lockout today
uses `198.51.100.7` (the proxy). With `trusted_hops = 1` it should use
`203.0.113.10` (the client).
### Not required. Suggest how to implement the addition or change
Root cause is in `mochiweb_request:get(peer, …)` (mochiweb v3.4.0): for
sockets in private ranges it returns
`string:strip(lists:last(string:tokens(XFF, ",")))` — the **last** XFF entry,
with no knob to configure it.
Rather than changing mochiweb (legacy, shared by many consumers), CouchDB
could resolve the client IP in its own layer: read the configured forwarded
header(s), apply the trusted-hops / trusted-proxy logic, and pass the result to
the lockout. The lockout's `peer/1` in `couch_auth_lockout.erl` currently
delegates straight to `mochiweb_request:get(peer, …)`; it could instead use the
CouchDB-resolved IP, paralleling how CouchDB already consumes `x_forwarded_*`
for host/proto/ssl.
### Additional Context
Behind a CDN/reverse proxy the lockout is effectively neutralised: the
rightmost `X-Forwarded-For` entry is a shared proxy egress address, so (a)
brute-force attempts spread across many proxy IPs rarely reach the per-`(IP,
user)` threshold, and (b) legitimate clients sharing a proxy egress IP can
trigger cross-lockouts / a self-DoS of a known username. Reverse proxies
already expose this control (nginx, Traefik, HAProxy), but CouchDB has no
equivalent — even though running behind a proxy is a documented, common
deployment.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]