The old README opened with project history and one list of a hundred settings. The new one leads with what smallwebwaf is, what it protects against, how to build and deploy it, how it sits in front of the app, what happens to a request, the settings most deployments touch, how to check it works and how to develop it. The reference material, every setting, bans, rule files, the Core Rule Set, the admin endpoints, the request log, alerts, metrics, state files, lookups, reputation sources, the image and gitea, moves to files under docs/, each linked from the README. Every statement was checked against the code on next. Model: fable-5-1
4.9 KiB
State files
smallwebwaf keeps its state in memory, and a copy of it in five JSON files in
SWWAF_STATE_DIR. The files are meant for people as well: you can read or edit
them at any time, and the running smallwebwaf takes the edit in. The
requirements they meet are under "Persistent state" in SPEC.md.
The files
Each has a top-level version of 1.
-
bans.json: active and past bans, up toSWWAF_MAX_BANSthatsmallwebwafmade and every ban you made, indented to be read. Per entry:- the netblock, start and expiry (
nullfor permanent); - the cause:
attack,limit,adminorcrowdsec; - a short reason;
- when it was lifted, if you lifted it;
- the notes (see
bans.md).
- the netblock, start and expiry (
-
clients.json: per client, its minute, hour and day counters and its history since it was first seen, one client per line, sogrepshows everything about one. The history holds:- 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.
Clients that were never banned are kept too, so every client's history survives a restart.
-
lookups.json: GeoJS answers, one per line: the AS number, AS name and country, when GeoJS was asked and 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 thing counted, 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.
Times are RFC 3339 UTC. Durations and sizes are plain numbers, with the unit in
the field name. bans.json, reputation.json and alerts.json are indented;
clients.json and lookups.json put each entry on one line.
Sizes
clients.json takes 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 takes about 1.2 KiB per ban, at most about 2.5
KiB, so about 6 MiB at the default SWWAF_MAX_BANS. With a full file, a hundred
new bans a day come to about 600 MiB of writes. lookups.json takes about 150
bytes per answer, under 1.5 GiB of writes a day when full. The other two files
are usually a few MiB or less.
Writing
bans.json is written SWWAF_STATE_WRITE_DELAY after a ban is made, lifted or
made permanent. Every file is written every SWWAF_STATE_COUNTER_INTERVAL, and
when smallwebwaf stops. Each write goes to a temporary file that then replaces
the file, so a crash leaves the old file or the new one, whole. Before writing a
file, smallwebwaf takes in any edit you made to it, so your edit is not
overwritten. A write that fails is logged, raised as a file_error alert, and
tried again at the next write. A hard kill loses what changed since the last
write:
- ban changes from the last
SWWAF_STATE_WRITE_DELAY(10 seconds); - everything else from the last
SWWAF_STATE_COUNTER_INTERVAL(15 minutes):- counts and history, and the counts in ban notes;
- GeoJS answers;
- reputation verdicts and the AbuseIPDB count;
- anomaly counters and alert cooldowns.
Reading at start
The files are read back. Each client keeps its counts, so a restart gives no one a fresh allowance. Each ban keeps refusing until it ends. Counter buckets and cache entries whose time has passed are discarded. A missing file is empty state. These stop the start, with a message naming the file and the place:
- a file that does not parse, or has another
version; - an entry without a field it needs;
- a ban whose
causeis notlimit,attack,adminorcrowdsec; - a ban whose
expiresis not after itsstart.
Editing while it runs
smallwebwaf watches the directory and takes in your edit of a file as soon as
you save it. What the file then holds replaces what smallwebwaf held for it.
It tells its own writes from yours by comparing the file with what it last read
or wrote. A change it made after you opened the file, such as a new ban, is lost
when you save over it; most editors warn when a file changed on disk while it
was open. An edit with an error that would stop the start does not stop the
running smallwebwaf. It keeps what it holds. At the file's next write it
renames your file to <name>.bad, writes the file again from memory, and logs
and alerts the file and the place of the error. Mend the .bad file and move it
back. A file you remove is written again at its next write.