1 Commits
Author SHA1 Message Date
clawbot 2369dc1081 New defaults for the request and byte limits (closes #161)
check / check (push) Canceled after 0s
A client is one IPv4 address or one IPv6 group, often several people
behind one NAT. The limits now sit about twice above what 40 people
busy with heavy web apps make together on one address: 6000 requests a
minute, 100,000 an hour and 1,000,000 a day; 4 GiB a minute, 20 GiB an
hour and 200 GiB a day. The largest response drops from 5 GiB to
1 GiB, so the minute byte limit still holds two of them. SPEC.md gives
the new reasoning; README.md and the reference documents give the new
figures.

Model: opus-5-5
2026-10-27 17:37:37 +00:00
3 changed files with 17 additions and 23 deletions
+9 -8
View File
@@ -376,15 +376,16 @@ Conventions:
### 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. A client is one IPv4 address or one IPv6 group,
often several people behind one NAT. 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.
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`.
A client slower than those 40 people cannot be told from them by counting. An
abuser that slow is caught by the trap paths, the rule files and the blocklists
instead. A 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
+2 -2
View File
@@ -35,8 +35,8 @@ checked again when gitea or the Core Rule Set changes version.
43,200 requests a day. While it runs a job, it reports the job's log and state
every second instead, two requests a second. So one runner busy all day sends
172,800 requests, under the request limits. Six such runners on one address,
each busy all day, pass the day limit of 1,000,000 within two days; five stay
under it. Their address is then banned, their running jobs fail, and each
each busy all day, pass the day limit of 1,000,000 after about 23 hours; five
stay under it. Their address is then banned, their running jobs fail, and each
repeat within a day makes the ban longer. Newer runners ask for work less
often. Put the runners' addresses in `SWWAF_RATE_LIMIT_EXEMPT_NETS`.
+6 -13
View File
@@ -60,19 +60,8 @@ func TestHealthCheck(t *testing.T) {
}, 0, "")
}
// Another test can take a closed server's port at once, so the app's
// address here is a multicast address, to which TCP cannot connect.
wantHealthCheck(t, map[string]string{
listenAddr: ":" + port,
upstreamURL: "http://224.0.0.1",
}, 1, "unhealthy: connect to the app: ")
// Listening on port 0 takes any free port, so nothing listens on port 0
// itself.
wantHealthCheck(t, map[string]string{listenAddr: ":0"}, 1,
"unhealthy: ask smallwebwaf: ")
wantHealthCheck(t, map[string]string{listenAddr: "8080"}, 1,
"unhealthy: invalid setting: SWWAF_LISTEN_ADDR: ")
app.Close()
wantHealthCheck(t, env, 1, "unhealthy: connect to the app: ")
stop()
@@ -81,6 +70,10 @@ func TestHealthCheck(t *testing.T) {
case <-time.After(waitLimit):
t.Fatal("still running after being told to stop")
}
wantHealthCheck(t, env, 1, "unhealthy: ask smallwebwaf: ")
wantHealthCheck(t, map[string]string{listenAddr: "8080"}, 1,
"unhealthy: invalid setting: SWWAF_LISTEN_ADDR: ")
}
func TestHealthCheckRefusesAnArgument(t *testing.T) {