waf: refuse request lines and header lines over 8 KiB first (closes #339)
check / check (push) Failing after 1m47s
check / check (push) Failing after 1m47s
The header limits now also refuse a request line over 8 KiB with 414 (action request_line_too_long) and a header line over 8 KiB, Host included, with 431. Like the other header limits they are fixed, run first and make no ban. One long query string or cookie no longer keeps the Core Rule Set busy for a third of a second. Model: opus-5-5
This commit is contained in:
1 parent
3550956cbb
commit
b0ac6fd9ce
10 files changed
+241
-39
No files matched your search
@@ -151,11 +151,11 @@ field gives that name. `refusal_limit` and `byte_limits` give theirs in
|
||||
around its address, a /64 by default, since one abuser usually controls a
|
||||
whole /64. A client is therefore one IPv4 address or one IPv6 group.
|
||||
3. The header limits (`header_limits`; see "Answering in time"). They come first
|
||||
after `SWW_WAF_ALLOW_NETS`, since they only count header fields and cookies.
|
||||
Next, the tag lists (`tag_lists`; see "Request tags"). Each list that holds
|
||||
the client adds its tag. Next, `routewatch_tags` adds the client's `asn=` and
|
||||
`prefix=` tags while `SWW_WAF_ROUTEWATCH_URL` is set. A client in
|
||||
`SWW_WAF_ALLOW_NETS` skips the header limits and gets no tag.
|
||||
after `SWW_WAF_ALLOW_NETS`, since they only measure lines and count header
|
||||
fields and cookies. Next, the tag lists (`tag_lists`; see "Request tags").
|
||||
Each list that holds the client adds its tag. Next, `routewatch_tags` adds
|
||||
the client's `asn=` and `prefix=` tags while `SWW_WAF_ROUTEWATCH_URL` is set.
|
||||
A client in `SWW_WAF_ALLOW_NETS` skips the header limits and gets no tag.
|
||||
4. The static lists. A client in `SWW_WAF_ALLOW_NETS` skips steps 5 to 15, the
|
||||
byte limits and the refusal limit. A client in `SWW_WAF_DENY_NETS` is refused
|
||||
(`deny_nets`); a client in both lists is let through.
|
||||
@@ -252,9 +252,9 @@ does not reach neighbours who did nothing. Requests refused under a ban are not
|
||||
counted against limits. They are counted in the client's history and in the
|
||||
ban's notes.
|
||||
|
||||
A request over the header limits is refused with `431` before the bans are
|
||||
checked (see "Answering in time"). It makes no ban, makes no ban permanent and
|
||||
is not counted in a ban's notes.
|
||||
A request over the header limits is refused with `414` or `431` before the bans
|
||||
are checked (see "Answering in time"). It makes no ban, makes no ban permanent
|
||||
and is not counted in a ban's notes.
|
||||
|
||||
An offence is a request `waf` holds against the client. It is one of:
|
||||
|
||||
@@ -2381,7 +2381,7 @@ answer but the last below carries `X-Sww-Disposition`.
|
||||
of:
|
||||
- `SWW_WAF_BAN_RESPONSE`, for a refusal;
|
||||
- `403`, for a `block` rule or the Core Rule Set;
|
||||
- `431`, for a request over the header limits;
|
||||
- `414` or `431`, for a request over the header limits;
|
||||
- `404`, for a path under `/_sww/` that passes the checks, so that the app
|
||||
never sees that prefix.
|
||||
- `X-Sww-Disposition: close`, status `200`, no body. This takes the place of a
|
||||
@@ -2442,22 +2442,31 @@ never wait. These can still wait for GeoJS:
|
||||
- a rule file;
|
||||
- the Core Rule Set.
|
||||
|
||||
The header limits are fixed, with no setting. `waf` refuses a request over
|
||||
either one:
|
||||
The header limits are fixed, with no setting. A line's length is in bytes and
|
||||
does not count its line ending. `waf` refuses a request whose request line is
|
||||
longer than 8 KiB with `414`. An example is `GET /search?q=` followed by 30,000
|
||||
characters.
|
||||
|
||||
It refuses a request with `431` for any of:
|
||||
|
||||
- a header line longer than 8 KiB. Each value of a header sent twice is a line
|
||||
of its own. `Host` counts as a line.
|
||||
- more than 50 cookies. Each part of its `Cookie` headers between semicolons
|
||||
counts as one, unless it is empty or only spaces and tabs.
|
||||
- more than 100 header fields. A header sent twice counts twice. `Host` and
|
||||
`Transfer-Encoding` do not count. `X-Request-ID` and `X-Forwarded-Proto` do.
|
||||
|
||||
Real clients never reach these limits. The answer is `deny` with `431`, and the
|
||||
log line's action is `request_header_too_large`. The refusal makes no ban and is
|
||||
no offence.
|
||||
Real clients rarely reach these limits. nginx refuses lines over 8 KiB by
|
||||
default, and Apache's default limit is about the same. The answer is `deny`. The
|
||||
log line's action is `request_line_too_long` for `414` and
|
||||
`request_header_too_large` for `431`. The refusal makes no ban and is no
|
||||
offence.
|
||||
|
||||
The header limits are the first check after `SWW_WAF_ALLOW_NETS`. A request over
|
||||
them is refused before any later check runs. So it causes no lookup, no query to
|
||||
an outside source and no rule match, and the rate limits do not count it. A
|
||||
client under a ban or in `SWW_WAF_DENY_NETS` also gets `431` for such a request.
|
||||
client under a ban or in `SWW_WAF_DENY_NETS` also gets `414` or `431` for such a
|
||||
request.
|
||||
|
||||
The limits apply on every path and in every `SWW_WAF_CORE_RULE_SET_MODE`. A
|
||||
client in `SWW_WAF_ALLOW_NETS` skips them, as it skips the Core Rule Set. In
|
||||
@@ -2465,9 +2474,10 @@ client in `SWW_WAF_ALLOW_NETS` skips them, as it skips the Core Rule Set. In
|
||||
other check runs on it.
|
||||
|
||||
The Core Rule Set runs each of its rules on each cookie, so thousands of small
|
||||
cookies would keep it busy for over a second. Within the limits, one long cookie
|
||||
or query string can still keep it busy for a fraction of a second. So enough
|
||||
such requests at once can overload `waf` past
|
||||
cookies would keep it busy for over a second. One 30 KB cookie or query string
|
||||
would keep it busy for a third of a second or more. A request with several long
|
||||
`Cookie` lines, each within the limits, can keep it as busy. Enough such
|
||||
requests at once can still overload `waf` past
|
||||
`SWW_RPROXY_WAF_BACKEND_TIMEOUT_MS`.
|
||||
|
||||
### The report
|
||||
|
||||
Reference in new issue
Block a user