README and SPEC say a client too slow to send its request line and headers may get an error answer (closes #138)
check / check (push) Canceled after 0s

A client too slow to send its request line and headers within
SWWAF_CLIENT_REQUEST_TIMEOUT gets either no answer or an error answer
from Go's server, mostly 400 Bad Request; either way its connection is
closed, nothing reaches the app, and no request log line is written.
The README's "Request log" and SPEC's size and time limits said such a
client always gets no answer. Both documents' summaries of
smallwebwaf's own answers now cover only limits passed after the
request line and headers have been read, and give 408 only for a slow
body; SPEC names Go's server as the one answering 431.

Model: opus-5-5
This commit was merged in pull request #145.
This commit is contained in:
2026-10-20 16:32:08 +02:00
parent 7acc6ae153
commit d1d21a0469
2 changed files with 31 additions and 27 deletions
+15 -13
View File
@@ -113,16 +113,16 @@ in `bin/state` unless `SWWAF_STATE_DIR` is set, and the default rule file of
`X-Forwarded-Proto`, and `X-Forwarded-For` with the peer added at the end. It `X-Forwarded-Proto`, and `X-Forwarded-For` with the peer added at the end. It
also gets the request's id in `X-Request-ID`, the same id as in the request's also gets the request's id in `X-Request-ID`, the same id as in the request's
log line (see `request_id` in "Request log" below). log line (see `request_id` in "Request log" below).
- Enforces the timeouts and the size limits below. A limit passed before the - Enforces the timeouts and the size limits below. Once a request's line and
response has started gets `smallwebwaf`'s own answer: `408` for a client too headers have been read, a limit passed before the response has started gets
slow to send its request, `413` for a request body that is too large, `504` `smallwebwaf`'s own answer: `408` for a client too slow to send its body,
for an app too slow to answer, and `502` for a response that is too large or `413` for a request body that is too large, `504` for an app too slow to
an app that cannot be reached. A request that announces a body over the limit answer, and `502` for a response that is too large or an app that cannot be
is refused before anything reaches the app. While a request body is still on reached. A request that announces a body over the limit is refused before
its way, a request timeout that runs out answers `408` if `smallwebwaf` was anything reaches the app. While a request body is still on its way, a request
waiting for the client to send more, and `504` if it was waiting for the app timeout that runs out answers `408` if `smallwebwaf` was waiting for the
to take what it had. Once the response has started, a limit can only cut the client to send more, and `504` if it was waiting for the app to take what it
connection. had. Once the response has started, a limit can only cut the connection.
- Counts each client's requests over a minute, an hour and a day. A request that - Counts each client's requests over a minute, an hour and a day. A request that
takes the client over one of the rate limits below is refused with takes the client over one of the rate limits below is refused with
`SWWAF_BAN_RESPONSE`, `403` by default, before anything reaches the app, and `SWWAF_BAN_RESPONSE`, `403` by default, before anything reaches the app, and
@@ -1045,9 +1045,11 @@ less severe than `SWWAF_LOG_LEVEL` are not written.
Go's HTTP server, on which `smallwebwaf` is built, reads a request's line and Go's HTTP server, on which `smallwebwaf` is built, reads a request's line and
headers before `smallwebwaf` sees the request, and some requests end there, headers before `smallwebwaf` sees the request, and some requests end there,
without a line in the log: headers over `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES`, without a line in the log: headers over `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES`,
which it answers `431`, headers slower than `SWWAF_CLIENT_REQUEST_TIMEOUT`, which it answers `431`, and requests it cannot read at all, which it answers
whose connection it closes without an answer, and requests it cannot read at itself, mostly with `400`. A client too slow to send its request line and
all, which it answers itself, mostly with `400`. headers within `SWWAF_CLIENT_REQUEST_TIMEOUT` gets either no answer or an error
answer from the server, mostly `400 Bad Request`; either way the server closes
its connection, nothing reaches the app, and no line is written in the log.
### Sending the log to a syslog server ### Sending the log to a syslog server
+16 -14
View File
@@ -414,10 +414,10 @@ The settings, by group:
to send its request line and headers, and then, from the end of the to send its request line and headers, and then, from the end of the
headers, its body. headers, its body.
- `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` (default `32K`): the largest - `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` (default `32K`): the largest
request line and headers a client may send. Over it, `smallwebwaf` answers request line and headers a client may send. Over it, Go's HTTP server
`431` and closes the connection, and nothing reaches the app. It must be answers `431` and closes the connection, and nothing reaches the app. It
more than `4K`, and cannot be `off`: Go's HTTP server always has such a must be more than `4K`, and cannot be `off`: Go's HTTP server always has
limit, and reads 4 KiB past the one it is given before it refuses. such a limit, and reads 4 KiB past the one it is given before it refuses.
- `SWWAF_CLIENT_IDLE_TIMEOUT` (default `120s`): how long a kept-open - `SWWAF_CLIENT_IDLE_TIMEOUT` (default `120s`): how long a kept-open
connection may wait for its next request before `smallwebwaf` closes it. connection may wait for its next request before `smallwebwaf` closes it.
It is longer than the 90 seconds after which traefik, by default, closes a It is longer than the 90 seconds after which traefik, by default, closes a
@@ -435,12 +435,13 @@ The settings, by group:
the client sends it and the app receives it. the client sends it and the app receives it.
- `SWWAF_RESPONSE_MAX_BYTES` (default `5G`): the largest response body, as - `SWWAF_RESPONSE_MAX_BYTES` (default `5G`): the largest response body, as
the app sends it and the client receives it. the app sends it and the client receives it.
- When a limit is passed before the response has started, `smallwebwaf` - When a limit is passed after a request's line and headers have been read,
answers itself: `413` for a request body that is too large, `408` for a but before the response has started, `smallwebwaf` answers itself: `413`
client that is too slow, `502` for a response that is too large, `504` for for a request body that is too large, `408` for a client too slow to send
an app that is too slow. A request that announces a body larger than its its body, `502` for a response that is too large, `504` for an app that is
limit is refused before anything reaches the app. Once the response has too slow. A request that announces a body larger than its limit is refused
started it can only be cut off, and the connection is closed. before anything reaches the app. Once the response has started it can only
be cut off, and the connection is closed.
- Since a request body streams through, each side can hold up the other: a - Since a request body streams through, each side can hold up the other: a
slow client slows the send to the app, and an app slow to take the body slow client slows the send to the app, and an app slow to take the body
slows the client's send. So while a request body is still on its way, a slows the client's send. So while a request body is still on its way, a
@@ -450,10 +451,11 @@ The settings, by group:
waiting for the app to take what it had. waiting for the app to take what it had.
- Go's HTTP server, on which `smallwebwaf` is built, reads a request's line - Go's HTTP server, on which `smallwebwaf` is built, reads a request's line
and headers before `smallwebwaf` sees the request. A client that takes and headers before `smallwebwaf` sees the request. A client that takes
longer than `SWWAF_CLIENT_REQUEST_TIMEOUT` to send them gets no answer: longer than `SWWAF_CLIENT_REQUEST_TIMEOUT` to send them gets either no
the server closes its connection. Headers over answer or an error answer from the server, mostly `400 Bad Request`;
`SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` are answered `431` by the server either way the server closes its connection and nothing reaches the app.
itself. Neither request gets a line in the request log. Headers over `SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES` are answered `431` by
the server itself. Neither request gets a line in the request log.
- A WebSocket connection leaves these limits behind once it is upgraded: it - A WebSocket connection leaves these limits behind once it is upgraded: it
stays open until either side closes it. stays open until either side closes it.
- Lookup of AS number and country (R7). On by default through GeoJS, which needs - Lookup of AS number and country (R7). On by default through GeoJS, which needs