rproxy, the proxy in front of each app, asks servewaf and fails open (closes #171)
check / check (push) Successful in 7m37s

`smallwebwaf rproxy` reads the first 64 KiB of each body, asks servewaf over
HTTP/1.1, and passes what servewaf allows to the app within its limits. Any
other answer goes to the visitor as servewaf gave it. SWRP_DEFAULT_DISPOSITION
decides only when servewaf cannot be connected to, does not answer at all, or
does not answer within SWRP_TIMEOUT_MS. A method SPEC.md does not list gets 405.

Duplication: internal/rproxy copies passing-on code from internal/proxy until
#172 removes the originals.
Rule suppressed: gosec G704 and G705; gosec at
internal/smallwebwaf/rproxy_test.go:431; tagliatelle at
internal/requestlog/requestlog.go:201; paralleltest on one test.
Judgement call: an answer over 1 MiB, or with a status below 200, gets 502.
Judgement call: every target not starting with one / gets 400.

Model: opus-5-5
This commit is contained in:
2026-11-05 05:04:21 +00:00
parent 4a4874ae2f
commit eabac85243
23 changed files with 6183 additions and 59 deletions
+13 -8
View File
@@ -10,9 +10,10 @@ refuses the ones that look like abuse. `smallwebwaf` is also a reverse proxy: it
accepts requests on the app's behalf, passes them to the app, and passes the
app's answers back.
It needs no setting. Every setting has a default chosen for a service on the
open internet. [`SPEC.md`](SPEC.md) says how `smallwebwaf` behaves and why. The
reference documents under [`docs/`](docs/) are listed under "Documents" below.
It needs no setting. Every `SWWAF_` setting has a default chosen for a service
on the open internet. [`SPEC.md`](SPEC.md) says how `smallwebwaf` behaves and
why. The reference documents under [`docs/`](docs/) are listed under "Documents"
below.
## What it protects against
@@ -342,15 +343,21 @@ pinned.
`127.0.0.1` and `::1` for forwarded headers, besides the private address
ranges.
- Both processes start with the container's environment variables, so every
setting of `smallwebwaf` starts with `SWWAF_`, and the app can read a token
given as one. A token given as a file that only the `smallwebwaf` user can
read is out of its reach (see "Settings given as files" in
setting of this `smallwebwaf` process starts with `SWWAF_`, and the app can
read a token given as one. A token given as a file that only the `smallwebwaf`
user can read is out of its reach (see "Settings given as files" in
[`docs/settings.md`](docs/settings.md)).
- The state files live in `/var/lib/smallwebwaf`. A volume mounted there keeps
them across a deploy.
- `smallwebwaf servewaf` runs the same checks for the sites that ask it about
each request, and passes nothing to an app (see "`servewaf`" in
[`SPEC.md`](SPEC.md)).
- `smallwebwaf rproxy` is the reverse proxy in front of one app that asks
`smallwebwaf servewaf` about each request. When `servewaf` cannot be connected
to, does not answer at all, or does not answer within `SWRP_TIMEOUT_MS`,
`SWRP_DEFAULT_DISPOSITION` decides. Its default, `allow`, keeps the site
answering. The settings of `rproxy` start with `SWRP_`, and it needs
`SWRP_WAF_BACKEND`, `servewaf`'s URL (see "`rproxy`" in [`SPEC.md`](SPEC.md)).
- `docker stop` stops both processes at once. `smallwebwaf` gives the requests
in progress five seconds to finish, so the app must keep answering for five
seconds after `SIGTERM`.
@@ -363,8 +370,6 @@ what each does.
## TODO
- Planned, as "Planned, not built" in [`SPEC.md`](SPEC.md) describes:
- `smallwebwaf rproxy`, the reverse proxy in front of each app that asks
`smallwebwaf servewaf` about each request;
- sharing bans between the instances of several apps;
- sending the log over RELP.