Files
smallwebwaf/docs/state-files.md
T
clawbot f408f42b28
check / check (push) Waiting to run
SPEC, README and docs rewritten from scratch (closes #154, closes #155, closes #156)
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)
2026-10-26 03:06:28 +01:00

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, start and expires (null for a permanent ban);
  • cause: attack, limit, admin or crowdsec;
  • 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_name and country: the client's, added when the lookup answers (empty when lookups are off);
  • for a broken limit, kind (requests, bytes or refusals), limit, window and count: what the limit was on, the limit, its window and the count reached;
  • limit_percent and limit_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_id and target, or trap_path;
  • reputation: the sources the client was on, each with its source and, for AbuseIPDB, its score;
  • request: the request that caused the ban, each text cut to 256 bytes:
    • time, method and host;
    • path, with its query string;
    • status and user_agent;
  • requests and refused: 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_blocked and token_refused.

lookups.json

GeoJS answers, one per line:

  • client;
  • asn, as_name and country;
  • 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 default SWWAF_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 default SWWAF_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.json and alerts.json: usually a few MiB or less.