Settle the spec's open points after milestones 1 and 2 #46

Merged
clawbot merged 1 commits from issue-36-spec-open-points into next 2026-10-04 02:57:25 +02:00
2 changed files with 33 additions and 14 deletions
+11 -5
View File
@@ -230,7 +230,10 @@ goes through the candidates one by one.
answers, the reputation cache, the alerting state) held in memory and kept in answers, the reputation cache, the alerting state) held in memory and kept in
readable JSON files, written regularly and at every stop, so a restart loses readable JSON files, written regularly and at every stop, so a restart loses
nothing. Edit a file, or add a rule file, and the running `smallwebwaf` picks nothing. Edit a file, or add a rule file, and the running `smallwebwaf` picks
up the change. Nothing is read from disk while serving a request. up the change. Nothing is read from disk while serving a request. The files
come in milestone 3 or later (see the build order in [`SPEC.md`](SPEC.md));
until then the rate counters and the GeoJS answers are kept in memory only,
and a restart loses them.
- Health checks, the metrics, and listing, adding and lifting bans or asking why - Health checks, the metrics, and listing, adding and lifting bans or asking why
a given address was refused, all on the one port every request uses: under a given address was refused, all on the one port every request uses: under
`/_smallwebwaf/` on the app's own address, through traefik like any other `/_smallwebwaf/` on the app's own address, through traefik like any other
@@ -349,9 +352,10 @@ GeoJS web service, which needs no account and no file. This means that, by
default, the address of every new visitor is sent to GeoJS. Each answer is kept default, the address of every new visitor is sent to GeoJS. Each answer is kept
in memory for seven days, and many addresses are asked about in one request; in memory for seven days, and many addresses are asked about in one request;
writing the answers to disk, so that they survive a restart, comes in milestone writing the answers to disk, so that they survive a restart, comes in milestone
3 or later. GeoJS publishes no rate limit but may block a caller it thinks asks 3 or later (see the build order in [`SPEC.md`](SPEC.md)). GeoJS publishes no
too much; while it is not answering, new visitors count as coming from an rate limit but may block a caller it thinks asks too much; while it is not
unknown country, which `SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES` refuses. answering, new visitors count as coming from an unknown country, which
`SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES` refuses.
To keep your visitors' addresses on your own host, set To keep your visitors' addresses on your own host, set
`SWWAF_LOOKUP_SOURCE=off`, or use the database file instead of GeoJS: `SWWAF_LOOKUP_SOURCE=off`, or use the database file instead of GeoJS:
@@ -373,7 +377,9 @@ that link.
Neither source can place a private address, so a client on one, such as a Neither source can place a private address, so a client on one, such as a
visitor on your local network, another container or your monitoring, has no visitor on your local network, another container or your monitoring, has no
country: `SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES` refuses it unless you list it in country: `SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES` refuses it unless you list it in
`SWWAF_ALLOW_NETS`. Such addresses are never sent to GeoJS. `SWWAF_ALLOW_NETS`. Such addresses are never sent to GeoJS. In milestone 2,
which has no `SWWAF_ALLOW_NETS`, neither country list checks such a client; the
refusal comes with `SWWAF_ALLOW_NETS` in milestone 3 or later.
## How the code is laid out ## How the code is laid out
+22 -9
View File
@@ -437,6 +437,13 @@ The settings, by group:
an app that is too slow. A request that announces a body larger than its an app that is too slow. A request that announces a body larger than its
limit is refused before anything reaches the app. Once the response has limit is refused before anything reaches the app. Once the response has
started it can only be cut off, and the connection is closed. 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
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
request timeout that runs out, `SWWAF_CLIENT_REQUEST_TIMEOUT` or
`SWWAF_UPSTREAM_REQUEST_TIMEOUT`, answers `408` if `smallwebwaf` was
waiting for the client to send more at that moment, and `504` if it was
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 no answer:
@@ -1392,12 +1399,13 @@ holds any token file.
taking more than 60 seconds is cut off, whether it is a git push, an LFS taking more than 60 seconds is cut off, whether it is a git push, an LFS
object, a container image layer, a package file or a release attachment. object, a container image layer, a package file or a release attachment.
The client is answered `413` for a body that is too large, before anything The client is answered `413` for a body that is too large, before anything
reaches gitea when the request announces its size, or `408` for one that reaches gitea when the request announces its size, or `408` for one the
is too slow; the upload fails, and no one is banned for it. A gitea that client sends too slowly (`504` if gitea is too slow to take it); the
takes large uploads needs `SWWAF_REQUEST_MAX_BYTES`, upload fails, and no one is banned for it. A gitea that takes large
`SWWAF_CLIENT_REQUEST_TIMEOUT` and `SWWAF_UPSTREAM_REQUEST_TIMEOUT` raised uploads needs `SWWAF_REQUEST_MAX_BYTES`, `SWWAF_CLIENT_REQUEST_TIMEOUT`
to fit. The Core Rule Set does not read an upload's body, which streams and `SWWAF_UPSTREAM_REQUEST_TIMEOUT` raised to fit. The Core Rule Set does
through without being held in memory. not read an upload's body, which streams through without being held in
memory.
- At the defaults (see "Configuration surface", attack detection), the Core - At the defaults (see "Configuration surface", attack detection), the Core
Rule Set lets gitea's ordinary use through, apart from the refusals in the Rule Set lets gitea's ordinary use through, apart from the refusals in the
next note: browsing and views of files in a repository, with their next note: browsing and views of files in a repository, with their
@@ -1596,16 +1604,21 @@ holds any token file.
only while a list is set. A client on a private, loopback or link-local only while a list is set. A client on a private, loopback or link-local
address has no country, and neither list checks it. address has no country, and neither list checks it.
- Like milestone 1, it writes nothing to disk: the GeoJS answers and the - Like milestone 1, it writes nothing to disk: the GeoJS answers and the
rate counters are kept in memory only, and a restart loses them. rate counters are kept in memory only, and a restart loses them. The
header size and the idle time stay fixed at their defaults.
- The container image described under "Deployment", with runit and the - The container image described under "Deployment", with runit and the
container's health check. The health check calls `/_smallwebwaf/healthz`, container's health check. The health check calls `/_smallwebwaf/healthz`,
so milestone 2 answers that path, although the other admin endpoints come so milestone 2 answers that path, although the other admin endpoints come
later. later.
- After milestone 2, the rest of the design, in this order: - Milestone 3 and later: the rest of the design, in this order:
- static lists, the bans that broken request limits lead to, the ban ledger - static lists, the bans that broken request limits lead to, the ban ledger
and the JSON state files with edits taken in while running, exemptions, and the JSON state files with edits taken in while running, exemptions,
`observe` mode, the rest of the request log's fields, the metrics `observe` mode, the rest of the request log's fields, the metrics
endpoint; endpoint, and the header size and the idle time as settings
(`SWWAF_CLIENT_REQUEST_HEADER_MAX_BYTES`, `SWWAF_CLIENT_IDLE_TIMEOUT`).
With the static lists comes `SWWAF_ALLOW_NETS`, and from then on
`SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES` refuses a client on a private,
loopback or link-local address unless `SWWAF_ALLOW_NETS` lists it;
- rule files, the other admin endpoints, alerting to all three destinations, - rule files, the other admin endpoints, alerting to all three destinations,
remote log sending; remote log sending;
- AS number and country lookup for every client, from the file or GeoJS, - AS number and country lookup for every client, from the file or GeoJS,