Milestones 1 and 2: proxy with timeouts and size limits, rate limits, country lists and the image #40
@@ -230,7 +230,10 @@ goes through the candidates one by one.
|
||||
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
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
3 or later. GeoJS publishes no rate limit but may block a caller it thinks asks
|
||||
too much; while it is not answering, new visitors count as coming from an
|
||||
unknown country, which `SWWAF_EXCLUSIVELY_ALLOWED_COUNTRIES` refuses.
|
||||
3 or later (see the build order in [`SPEC.md`](SPEC.md)). GeoJS publishes no
|
||||
rate limit but may block a caller it thinks asks too much; while it is not
|
||||
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
|
||||
`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
|
||||
visitor on your local network, another container or your monitoring, has no
|
||||
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
|
||||
|
||||
|
||||
@@ -437,6 +437,13 @@ The settings, by group:
|
||||
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
|
||||
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
|
||||
and headers before `smallwebwaf` sees the request. A client that takes
|
||||
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
|
||||
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
|
||||
reaches gitea when the request announces its size, or `408` for one that
|
||||
is too slow; the upload fails, and no one is banned for it. A gitea that
|
||||
takes large uploads needs `SWWAF_REQUEST_MAX_BYTES`,
|
||||
`SWWAF_CLIENT_REQUEST_TIMEOUT` and `SWWAF_UPSTREAM_REQUEST_TIMEOUT` raised
|
||||
to fit. The Core Rule Set does not read an upload's body, which streams
|
||||
through without being held in memory.
|
||||
reaches gitea when the request announces its size, or `408` for one the
|
||||
client sends too slowly (`504` if gitea is too slow to take it); the
|
||||
upload fails, and no one is banned for it. A gitea that takes large
|
||||
uploads needs `SWWAF_REQUEST_MAX_BYTES`, `SWWAF_CLIENT_REQUEST_TIMEOUT`
|
||||
and `SWWAF_UPSTREAM_REQUEST_TIMEOUT` raised to fit. The Core Rule Set does
|
||||
not read an upload's body, which streams through without being held in
|
||||
memory.
|
||||
- At the defaults (see "Configuration surface", attack detection), the Core
|
||||
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
|
||||
@@ -1596,16 +1604,21 @@ holds any token file.
|
||||
only while a list is set. A client on a private, loopback or link-local
|
||||
address has no country, and neither list checks it.
|
||||
- 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
|
||||
container's health check. The health check calls `/_smallwebwaf/healthz`,
|
||||
so milestone 2 answers that path, although the other admin endpoints come
|
||||
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
|
||||
and the JSON state files with edits taken in while running, exemptions,
|
||||
`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,
|
||||
remote log sending;
|
||||
- AS number and country lookup for every client, from the file or GeoJS,
|
||||
|
||||
Reference in New Issue
Block a user