AbuseIPDB scores for clients that committed an offence, within a daily budget (closes #105)
check / check (push) Waiting to run

With SWWAF_ABUSEIPDB_KEY set, a client whose history counts an offence
(a broken limit, a ban rule's match or a block rule's refusal, counted
by kind) is checked in the background, at most
SWWAF_ABUSEIPDB_DAILY_BUDGET checks a day, the count kept in
reputation.json. A client, an IPv4 address or an IPv6 /64, is checked by
the address it sent from, and its score serves all its addresses. A
score at or over SWWAF_ABUSEIPDB_MIN_SCORE is a hit for
SWWAF_REPUTATION_ACTION, logged as abuseipdb and alerted with its score.
A failure or the used-up budget gives no score and raises
source_failure. The key goes only in the Key header.

Judgement call: the budget's day is UTC; AbuseIPDB documents no reset time.
Judgement call: each check sent spends budget; a minute's pause after a failure.

Model: opus-5-5
This commit is contained in:
2026-10-07 20:27:55 +00:00
parent 0b0f207423
commit e265e8cd04
23 changed files with 2045 additions and 309 deletions
+21 -4
View File
@@ -117,9 +117,15 @@ type Responses struct {
}
// Offences are a client's offences, by kind.
//
//nolint:tagliatelle // the state files use snake_case, as the request log does
type Offences struct {
// Limit is its requests that broke a rate limit or a byte limit.
Limit int64 `json:"limit"`
// Limit is its requests that broke a rate limit or a byte limit,
// Attack those that matched a ban rule, a clear sign of attack, and
// RuleBlocked those a block rule refused.
Limit int64 `json:"limit"`
Attack int64 `json:"attack"`
RuleBlocked int64 `json:"rule_blocked"`
}
// Request is what a client's history keeps of one of its requests.
@@ -137,8 +143,11 @@ type Request struct {
RequestBytes int64
ResponseBytes int64
// BrokeLimit is true for a request that broke a rate limit or a byte
// limit.
BrokeLimit bool
// limit, Attack for one that matched a ban rule, and RuleBlocked for
// one a block rule refused.
BrokeLimit bool
Attack bool
RuleBlocked bool
}
// New returns a Limiter for limits, with no client counted yet.
@@ -258,6 +267,14 @@ func (l *Limiter) AddToHistory(client netip.Prefix, now time.Time, r Request) {
if r.BrokeLimit {
h.Offences.Limit++
}
if r.Attack {
h.Offences.Attack++
}
if r.RuleBlocked {
h.Offences.RuleBlocked++
}
}
// AddLookup gives client's history its AS number, AS name and country, as