Ban notes name the reputation sources that listed the client (closes #109)
check / check (push) Waiting to run

A ban's notes, in bans.json and in its alert, gain `reputation`: each
blocklist, DNSBL zone or AbuseIPDB that listed the client when the ban
was made, as its `source`, named and ordered as in the request log's
`reputation`, with AbuseIPDB's `score`. It is left out when none did.
README.md shows it in a bans.json example.

Notes now hold a list, so bans can no longer be compared with ==: the
tests compare them with reflect.DeepEqual.

Judgement call: the score is a pointer, so a score of 0, a hit while
SWWAF_ABUSEIPDB_MIN_SCORE is 0, is still written.

Model: opus-5-5
This commit was merged in pull request #114.
This commit is contained in:
2026-10-08 03:08:01 +02:00
parent a6634454cd
commit 04e66d2069
16 changed files with 243 additions and 68 deletions
+13
View File
@@ -118,6 +118,10 @@ type Notes struct {
// of the rule file rule that matched, and its target.
RuleID string `json:"rule_id,omitempty"`
Target string `json:"target,omitempty"`
// Reputation is the reputation sources that listed the client when
// the request that caused the ban was made, in the order the request
// log's reputation names them. It is left out when none did.
Reputation []ReputationHit `json:"reputation,omitempty"`
// Request is the request that broke the limit, or whose bytes broke
// it, or that was the clear sign of attack.
Request Request `json:"request"`
@@ -131,6 +135,15 @@ type Notes struct {
EarlierBans EarlierBans `json:"earlier_bans"`
}
// ReputationHit is a reputation source that listed a client, as a
// reputation_hit alert's detail gives it: Source is the blocklist's URL,
// the DNSBL zone with its key masked, or "abuseipdb", and Score, for
// AbuseIPDB alone, its score of the client.
type ReputationHit struct {
Source string `json:"source"`
Score *int64 `json:"score,omitempty"`
}
// EarlierBans counts a netblock's bans before a ban, by cause.
type EarlierBans struct {
Limit int `json:"limit"`