check / check (push) Successful in 5m1s
Documents only. The byte limits and byte anomaly thresholds count body bytes, as SWW_BYTES_COUNT chooses them, with WebSocket traffic each way, once a response has ended; the request that passes a limit is not cut off and the client is banned. README.md, SPEC.md and docs/ now say so, and no longer call a response's bytes the request's. Also made plain: rate limits and their exemptions, the refusal threshold, SWRP_MAX_REQUEST_TIME_MS, SWRP_MAX_RESPONSE_SIZE, SWW_LOOKUP_SOURCE, SWW_LIMIT_BAN_REPEAT_WINDOW, the metrics' byte series, and the SPEC.md claim about answering within SWRP_TIMEOUT_MS. EVALUATION.md is audited too; its survey facts and date are unchanged. Model: fable-5-1 (first audit); opus-5-5 (rework)
3.7 KiB
3.7 KiB
State files
The five JSON files in SWW_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 SWW_MAX_BANS of those
discriminator 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;
- body bytes of its requests, and of the responses it was sent;
- responses by status class;
- offences by kind:
limit,attack,rule_blockedandwaf_blocked. A file may also holdtoken_refused, which is kept, and which nothing adds to.
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 defaultSWW_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 defaultSWW_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.