servewaf always answers rproxy well within its time limit (closes #182)
check / check (push) Failing after 15m18s

A question waits on GeoJS at most 800ms, the new default of
SWWAF_LOOKUP_TIMEOUT. In enforce mode it does not wait at all when it is
over the header limits, on a fetched blocklist with deny, on the CrowdSec
decision list, or over a whole rate limit. Not waiting never lowers a
client's limit. Just before the Core Rule Set, servewaf refuses more than
50 cookies or 100 header fields with 431.

Shared default changed: SWWAF_LOOKUP_TIMEOUT also applies to smallwebwaf
with no command.
Judgement call: SWWAF_REPUTATION_TIMEOUT stays 2s, since no request waits
on the DNS blocklists or AbuseIPDB.

Model: opus-5-5
This commit is contained in:
2026-11-05 04:11:56 +00:00
parent 2eeea136e8
commit 5a278949d7
22 changed files with 937 additions and 55 deletions
+24
View File
@@ -228,6 +228,30 @@ func (l *Limiter) Count(
return l.count(client, now, 1, 0, percent)
}
// OverARateLimit reports whether one more request from client at now would
// take it over a whole rate limit. A client's percentage can only lower a
// limit, so that request is over the limit at any percentage. It counts
// nothing, and does not make the client the most recently seen.
func (l *Limiter) OverARateLimit(client netip.Prefix, now time.Time) bool {
l.mu.Lock()
defer l.mu.Unlock()
c, seen := l.clients.Peek(client)
if !seen {
return false
}
buckets := c.buckets()
for i, w := range l.windows {
if w.limit > 0 && buckets[i].Add(now, w.length, 0)+1 > float64(w.limit) {
return true
}
}
return false
}
// CountBytes counts bytes, those of a request from client that has ended,
// at now, in every window, and returns the client's counts in each window.
// It reports whether the bytes take the client over a byte limit, of which