nginx trusts X-Forwarded-For from every private address, so the rate limit can be dodged #64

Open
opened 2026-09-29 03:39:25 +02:00 by clawbot · 0 comments
Collaborator

nginx.conf takes the client address from X-Forwarded-For when the request comes from any private-range address (set_real_ip_from 10/8, 172.16/12, 192.168/16). A client that reaches nginx from such an address, or through Docker's userland proxy (which makes every client appear as the gateway, for example 172.17.0.1), can write a new X-Forwarded-For on each request and so get a fresh rate-limit allowance each time (#20 keys the limit on that address). Found during the review of #63; it comes from #19 and #52.

Definition of done

  • The addresses nginx trusts for X-Forwarded-For come from an environment variable rendered into the nginx template (the template step of #26), with a default that trusts no forwarded header, so an operator names the proxy in front of the container.
  • The backend keeps trusting only nginx on loopback for the address nginx passes it.
  • Verified by running the image: with the default, a forged X-Forwarded-For does not change the address the rate limit sees; with the proxy's address set, the address the proxy appends is used.
  • The README (and the upaas section of #59, if it has landed) names the variable.
  • Root make check and script/cibuild pass; TODO.md updated in the same commit; commit title ends (closes #N).

Model: opus-5-5

`nginx.conf` takes the client address from `X-Forwarded-For` when the request comes from any private-range address (`set_real_ip_from` 10/8, 172.16/12, 192.168/16). A client that reaches nginx from such an address, or through Docker's userland proxy (which makes every client appear as the gateway, for example `172.17.0.1`), can write a new `X-Forwarded-For` on each request and so get a fresh rate-limit allowance each time (https://git.eeqj.de/sneak/netwatch/issues/20 keys the limit on that address). Found during the review of https://git.eeqj.de/sneak/netwatch/pulls/63; it comes from https://git.eeqj.de/sneak/netwatch/issues/19 and https://git.eeqj.de/sneak/netwatch/issues/52. ## Definition of done - The addresses nginx trusts for `X-Forwarded-For` come from an environment variable rendered into the nginx template (the template step of https://git.eeqj.de/sneak/netwatch/issues/26), with a default that trusts no forwarded header, so an operator names the proxy in front of the container. - The backend keeps trusting only nginx on loopback for the address nginx passes it. - Verified by running the image: with the default, a forged `X-Forwarded-For` does not change the address the rate limit sees; with the proxy's address set, the address the proxy appends is used. - The README (and the upaas section of https://git.eeqj.de/sneak/netwatch/issues/59, if it has landed) names the variable. - Root `make check` and `script/cibuild` pass; `TODO.md` updated in the same commit; commit title ends ` (closes #N)`. Model: opus-5-5
clawbot self-assigned this 2026-09-29 03:39:25 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/netwatch#64