Log the route pattern for redirected and rejected requests (closes #146)
All checks were successful
check / check (push) Successful in 2m57s
All checks were successful
check / check (push) Successful in 2m57s
The access log wrote one INFO line per request carrying r.URL.String(). Registered with Use, it runs ahead of the route limiter, so a client flooding the unauthenticated receiver with invented paths wrote attacker-chosen text of attacker-chosen length into the operator's log, one line per request. 3xx and 4xx responses now log the chi route pattern in place of the concrete URL, and the fixed literal "(unmatched)" when routing matched nothing at all. One line per request is retained, so real traffic stays observable and rate accounting still works, but the line's content is now bounded by the service's own route table. 2xx and 5xx keep the full URL. The pattern is only populated after routing, so it is read in the deferred part of the handler rather than before next.ServeHTTP. No other access-log field changes.
This commit is contained in:
20
README.md
20
README.md
@@ -904,8 +904,24 @@ requests and has the rest of its aggregate budget rejected there, so
|
||||
the aggregate limit is what bounds those `WARN` lines — to under ten
|
||||
times `RECEIVER_RATE_LIMIT` per minute per client IP, 1080 at the
|
||||
defaults, where before it there was no bound at all. The access log is
|
||||
bounded by neither limit: every request is recorded once at `INFO` with
|
||||
its full URL, served or rejected alike.
|
||||
bounded by neither limit: every request is recorded once at `INFO`,
|
||||
served or rejected alike.
|
||||
|
||||
What the access log does bound is the _content_ of those lines. A 3xx
|
||||
or 4xx response logs the chi route pattern — `/webhook/{uuid}`,
|
||||
`/user/{username}//`, or the literal `(unmatched)` when the request hit
|
||||
no route at all — in place of the concrete URL. Those are the outcomes
|
||||
an unauthenticated client can drive for free: 404 and 429 on any
|
||||
invented receiver path, a login redirect on any invented profile path.
|
||||
Logging the URL there would let a flood write text of its own choosing,
|
||||
at a length of its own choosing, into the log. The pattern comes from
|
||||
the service's own route table, so an operator sizing log storage can
|
||||
multiply a fixed per-line cost by the request rate the rate limits
|
||||
allow. 2xx and 5xx responses keep the full URL, query string included:
|
||||
a success resolved against a static route or against the operator's own
|
||||
data (on the receiver, against a stored entrypoint UUID), and a 5xx is
|
||||
a bug in this service, where the exact URL is the evidence and no
|
||||
client can provoke one at will.
|
||||
|
||||
Every limiter here — receiver, login, and password change — identifies
|
||||
the client the same way, through one shared key function: the
|
||||
|
||||
Reference in New Issue
Block a user