Compare commits

..
Author SHA1 Message Date
sneak 948ced2cbf README: blocks misbehaving scrapers, not normal ones (closes #387)
check / check (push) Failing after 2m12s
The opening now lists what bans a client with the default settings: the
rate and byte limits, a probe for a secret path, a security scanner's
user agent, and the refusal limit. A scraper that does none of these is
left alone.

Model: opus-5-5
2026-11-14 17:10:54 +00:00
+15 -20
View File
@@ -2,7 +2,20 @@
`smallwebwaf` is an MIT-licensed web application firewall, written in Go by
[@sneak](https://sneak.berlin), for self-hosted web apps. It refuses the
requests of scrapers, scanners and other abusers before they reach an app.
requests of misbehaving scrapers, scanners and other abusers before they reach
an app.
With the default settings, a client is banned when it does any of these:
- makes more than 120 requests in a minute, 1500 in an hour or 6000 in a day;
- moves more than `50G` of request and response bodies in an hour, or `100G` in
a day;
- asks for a secret or backup file, such as `/.env` or `/.git/config`;
- sends a user agent that names a security scanner, such as `sqlmap` or `nikto`;
- has more than 30 requests in a minute refused as probes or attacks.
A scraper that does none of these is left alone. A scraper that waits 15 seconds
between requests stays under the rate limits.
## What it does
@@ -22,25 +35,7 @@ shipped in one image, with two commands that do this together:
The site keeps answering while `waf` is down, slow or restarting: without an
answer in time, `rproxy` passes the request to the app.
`rproxy` also protects the app on its own, whether or not `waf` answers. It
limits the total size of a request's headers, but not their number: the limits
on the number of headers and cookies, and on each header line's length, are
`waf`'s. With the default settings, `rproxy`:
- answers `400` to a malformed request, such as a broken header line or a
missing `Host`;
- answers `405` to a method it does not pass on, such as `TRACE`;
- answers `431` to a request line and headers over 32 KiB together;
- gives the visitor 60 seconds to send the request line and headers, and then 60
seconds more for the whole request to reach the app;
- answers `413` to a request body over 100 MiB;
- gives the app's answer 30 minutes to reach the visitor, counted from the end
of the request;
- answers `502` in place of an app's answer whose body is over 1 GiB, or cuts it
off if it has started;
- closes a kept-open connection after 120 seconds idle.
Together, `rproxy` and `waf` protect against:
It protects against:
- Scrapers that fetch every page of a site, all day. Each client gets a limit on
requests and on body bytes per minute, per hour and per day. The defaults