check / check (push) Waiting to run
SPEC.md is the only place that says how smallwebwaf behaves and why; docs/ holds lists linking to it; the README is short and links to both. Passed independent review in round 8. Model: fable-5-1 (writing); opus-5-5 (review, merge)
3.6 KiB
3.6 KiB
State files
The five JSON files in SWWAF_STATE_DIR, and what each holds. "Persistent
state" in SPEC.md says how they are written, read and edited.
Each has a top-level version of 1.
bans.json
Active and past bans: every ban an admin made, and up to SWWAF_MAX_BANS of
those smallwebwaf made. Per entry:
netblock,startandexpires(nullfor a permanent ban);cause:attack,limit,adminorcrowdsec;reason: a short reason;lifted: when an admin lifted it, if one did;notes: the notes below.
An entry an admin adds needs netblock, start and expires; reason,
notes and cause may be left out, and the cause is then admin:
{
"version": 1,
"bans": [
{
"netblock": "203.0.113.0/24",
"start": "2026-10-06T12:00:00Z",
"expires": null,
"reason": "probes for logins"
}
]
}
"Bans" in SPEC.md says how an edit lifts, keeps or forgets a
ban. The notes:
asn,as_nameandcountry: the client's, added when the lookup answers (empty when lookups are off);- for a broken limit,
kind(requests,bytesorrefusals),limit,windowandcount: what the limit was on, the limit, its window and the count reached; limit_percentandlimit_percent_setting: the client's percentage of that limit and the setting that gave it, when a setting lowered it;- for a clear sign of attack,
rule_idandtarget, ortrap_path; reputation: the sources the client was on, each with itssourceand, for AbuseIPDB, itsscore;request: the request that caused the ban, each text cut to 256 bytes:time,methodandhost;path, with its query string;statusanduser_agent;
requestsandrefused: the netblock's requests since it was first seen, and how many this ban has refused so far, kept up to date while the ban lasts;earlier_bans: how many earlier bans the netblock had, by cause.
clients.json
Per client, one per line: its minute, hour and day counters, and its history since it was first seen:
- the first and last time seen;
- the AS number, AS name and country last looked up, and when;
- total requests, and how many were forwarded and how many refused;
- bytes in each direction;
- responses by status class;
- offences by kind:
limit,attack,rule_blocked,waf_blockedandtoken_refused.
lookups.json
GeoJS answers, one per line:
client;asn,as_nameandcountry;answered: when GeoJS answered;used: when the answer was last used.
reputation.json
- the last good copy of each list fetched from a URL, with when it was last tried;
- each DNS blocklist verdict still in use;
- AbuseIPDB's scores, and the checks spent today.
alerts.json
- the anomaly counters;
- the alert cooldowns: for each event and netblock, source, file or anomaly scope, when it was last sent and the count of repeats held back since;
- the alerts sent and held back in the current hour;
- the alerts waiting for each destination.
Sizes
clients.json: about 1 KiB per client, about 20 MiB at the defaultSWWAF_MAX_TRACKED_CLIENTS. Written every 15 minutes, that is under 2 GiB of disk writes a day.bans.json: about 1.2 KiB per ban, at most about 2.5 KiB, so about 6 MiB at the defaultSWWAF_MAX_BANS. Written every 15 minutes, a full file comes to about 600 MiB of writes a day, and a hundred new bans a day add about 600 MiB more.lookups.json: about 150 bytes per answer, under 1.5 GiB of writes a day when full.reputation.jsonandalerts.json: usually a few MiB or less.