Default request limits per hour and per day, sized for API use (closes #176)
check / check (push) Successful in 6m13s

The default request limits now suit programmatic use of an API, such
as an automation fleet on another host, and still catch crawlers:

- per minute: off;
- per hour: 30000, passed by a crawler that keeps up 10 a second;
- per day: 300000, passed by one that keeps up 4 a second.

The byte limits and ban lengths are unchanged. SPEC.md, README.md and
docs/settings.md give the reasons and what counting cannot catch;
docs/gitea.md redoes the Actions runner sums.

Judgement call: the ban alert example in docs/alerts.md now shows the
hour limit, since the minute limit is off by default.

Model: opus-5-5
This commit is contained in:
2026-11-04 19:18:40 +00:00
parent fdabf4974b
commit 1f71568d02
8 changed files with 71 additions and 47 deletions
+26 -17
View File
@@ -369,22 +369,31 @@ Conventions:
owner's own networks. `SWWAF_RATE_LIMIT_EXEMPT_NETS` bypasses the request and
byte limits only; the error burst, attack detection and bans still apply.
- Many people can share one address, as in an office, on a mobile carrier or
through Tor. They are one client, and share its limits and its bans. The
default limits are sized for about 40 busy people on one address. A known
shared address busier than that belongs in `SWWAF_ALLOW_NETS` or
through Tor. They are one client, and share its limits and its bans. A known
shared address busier than the limits allow belongs in `SWWAF_ALLOW_NETS` or
`SWWAF_RATE_LIMIT_EXEMPT_NETS`.
### Request rate limits, per client
Breaking one bans the client, so the defaults sit about twice above what 40
people busy with heavy web apps make together on one address. Each such person
makes about 75 requests in a busy minute, and 1,250 an hour for ten hours a day.
Breaking one bans the client. The defaults suit programmatic use of an API, such
as an automation fleet on another host, and still stop abusive bots. They count
per hour and per day, so a short burst of requests breaks no limit on its own.
A client slower than those 40 people cannot be told from them by counting. Only
the other checks can catch an abuser that slow. They include the trap paths, the
rule files, the Core Rule Set and the blocklists. An abuser that trips none of
them is not caught. A machine that talks to the app all day can still pass the
day limit. Its address belongs in `SWWAF_RATE_LIMIT_EXEMPT_NETS`.
- Per minute: `off`.
- Per hour: 30,000, about 8 requests a second for a whole hour. A crawler that
keeps up 10 a second makes 36,000 an hour, and passes it.
- Per day: 300,000, about 3.5 requests a second around the clock. A crawler that
keeps up 4 a second makes 345,600 a day, and passes it.
A fleet of 20 agents, each making a request every 10 seconds, makes 7,200
requests an hour. Working around the clock, it makes 172,800 a day. Both stay
under the limits.
Counting cannot catch a client slower than these limits. Only the other checks
can catch an abuser that slow. They include the trap paths, the rule files, the
Core Rule Set and the blocklists. An abuser that trips none of them is not
caught. A busier machine that talks to the app all day can still pass the day
limit. Its address belongs in `SWWAF_RATE_LIMIT_EXEMPT_NETS`.
`SWWAF_RATE_LIMIT_EXEMPT_PATHS` takes path prefixes out of the count, such as
static assets or health checks; their bytes are not counted either. A prefix is
@@ -397,12 +406,12 @@ matched the same way.
### Byte limits, per client
Each of the same 40 people moves about 256 MiB an hour, for ten hours a day. The
hour and day limits sit about twice above what they move together. A response's
bytes are counted when it ends (see step 15). So the minute limit holds two of
the largest responses, with their requests, ending in the same minute. No single
download then breaks a limit. An operator who raises `SWWAF_RESPONSE_MAX_BYTES`
raises the byte limits with it.
The hour and day limits sit about twice above what 40 people busy with heavy web
apps move together on one address. Each moves about 256 MiB an hour, for ten
hours a day. A response's bytes are counted when it ends (see step 15). So the
minute limit holds two of the largest responses, with their requests, ending in
the same minute. No single download then breaks a limit. An operator who raises
`SWWAF_RESPONSE_MAX_BYTES` raises the byte limits with it.
### Size and time limits