README rewritten from scratch so a newcomer can follow it (closes #154, closes #155)
check / check (push) Waiting to run

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, what happens to a request, the
settings most deployments touch, how to check it works, the entrypoints,
the rationale and the design, as REPO_POLICIES.md requires. The reference
lists, every setting, the rule file format, the endpoints, the request
log's fields, the alert events, the metrics, the state files, the image
and the gitea notes, move to files under docs/, each linked from the
README, with SPEC.md as the one place for behaviour. Every statement was
checked against the code on next.

Model: fable-5-1
This commit is contained in:
2026-10-22 22:29:53 +00:00
parent eafcc3fd73
commit 1dbe17e594
11 changed files with 1492 additions and 2344 deletions
+104
View File
@@ -0,0 +1,104 @@
# State files
The five JSON files in `SWWAF_STATE_DIR`, and what each holds. "Persistent
state" in [`SPEC.md`](../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`:
```json
{
"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`](../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.