Bans: the ban model of issue 2, with the notes of issue 4 #18

Open
opened 2026-09-25 11:01:48 +02:00 by clawbot · 2 comments
Collaborator

Bans as sneak set them out in #2: seven days for a clear sign of attack and permanent on a repeat; an hour for a broken limit, longer on each repeat, permanent past seven days. Each ban carries the notes of #4, and the ban file can be edited while smallwebwaf runs, as the "Bans" and "Persistent state" sections of SPEC.md (#9) describe. Milestone 2 refuses a client while it is over a limit and bans no one (#14).

Not scheduled: it waits for sneak to put it in a milestone.

Model: opus-5-5

Bans as sneak set them out in https://git.eeqj.de/sneak/smallwebwaf/issues/2: seven days for a clear sign of attack and permanent on a repeat; an hour for a broken limit, longer on each repeat, permanent past seven days. Each ban carries the notes of https://git.eeqj.de/sneak/smallwebwaf/issues/4, and the ban file can be edited while smallwebwaf runs, as the "Bans" and "Persistent state" sections of `SPEC.md` (https://git.eeqj.de/sneak/smallwebwaf/pulls/9) describe. Milestone 2 refuses a client while it is over a limit and bans no one (https://git.eeqj.de/sneak/smallwebwaf/issues/14). Not scheduled: it waits for sneak to put it in a milestone. Model: opus-5-5
Author
Collaborator

Plan. The build order in SPEC.md puts the bans that broken request limits lead to right after the static lists (#19), so they are built next, as "Bans" describes, in memory only. Writing them to bans.json and reading them at start come with the state files (#17); bans for a clear sign of attack come with the rule files.

  • A request over a request limit is refused with SWWAF_BAN_RESPONSE and bans the client's netblock (its IPv4 address, widened by SWWAF_BAN_SCOPE_V4_PREFIX, or its IPv6 group): SWWAF_LIMIT_BAN_DURATION for a first ban, three times the last one when the limit is broken again within SWWAF_LIMIT_BAN_REPEAT_WINDOW after it ended, and permanent once that would pass SWWAF_MAX_BAN_DURATION. Each such ban sets the client's counters back to zero. Its log line keeps action rate_limited and limit_hit, and gains offence and ban_expires.
  • The ban ledger is checked after the static lists and before the lookup: a request from a banned netblock is refused with SWWAF_BAN_RESPONSE, logged with action banned and ban_expires, not counted against limits, and counted in the ban's notes.
  • At most SWWAF_MAX_BANS bans are held; when full, the one whose netblock has gone longest without a request is dropped first.
  • Each ban carries the notes "Persistent state" lists, as far as they are known at this stage: the limit, its window and the count reached; the AS number, AS name and country when looked up; the last ten requests that counted toward it, each text cut to 256 bytes; how many requests counted and over what time; the requests refused under it; earlier bans of each kind. The netblock's total since it was first seen comes with the client history in #17. Memory stays bounded; the PR body says what the notes cost at the default bounds.
  • SWWAF_BAN_RESPONSE (403, 429 or close) also answers the country lists and SWWAF_DENY_NETS, as "Data flow for one request" says.
  • New settings, each with its default from "Configuration surface": SWWAF_BAN_RESPONSE, SWWAF_LIMIT_BAN_DURATION, SWWAF_LIMIT_BAN_REPEAT_WINDOW, SWWAF_MAX_BAN_DURATION, SWWAF_MAX_BANS, SWWAF_BAN_SCOPE_V4_PREFIX; a value set but invalid stops the start. README.md documents them and the change from 429.

Definition of done: tests, on a clock the test controls, show a first ban, the threefold repeats, the permanent ban, the repeat window running out, counters reset by a ban, a banned netblock refused and not counted, the SWWAF_MAX_BANS bound dropping the right ban, SWWAF_BAN_SCOPE_V4_PREFIX, each SWWAF_BAN_RESPONSE value, the notes, the defaults and invalid values; make check green; one PR to next, passed by a reviewer who did not write it.

Model: opus-5-5

Plan. The build order in `SPEC.md` puts the bans that broken request limits lead to right after the static lists (https://git.eeqj.de/sneak/smallwebwaf/issues/19), so they are built next, as "Bans" describes, in memory only. Writing them to `bans.json` and reading them at start come with the state files (https://git.eeqj.de/sneak/smallwebwaf/issues/17); bans for a clear sign of attack come with the rule files. - A request over a request limit is refused with `SWWAF_BAN_RESPONSE` and bans the client's netblock (its IPv4 address, widened by `SWWAF_BAN_SCOPE_V4_PREFIX`, or its IPv6 group): `SWWAF_LIMIT_BAN_DURATION` for a first ban, three times the last one when the limit is broken again within `SWWAF_LIMIT_BAN_REPEAT_WINDOW` after it ended, and permanent once that would pass `SWWAF_MAX_BAN_DURATION`. Each such ban sets the client's counters back to zero. Its log line keeps `action` `rate_limited` and `limit_hit`, and gains `offence` and `ban_expires`. - The ban ledger is checked after the static lists and before the lookup: a request from a banned netblock is refused with `SWWAF_BAN_RESPONSE`, logged with `action` `banned` and `ban_expires`, not counted against limits, and counted in the ban's notes. - At most `SWWAF_MAX_BANS` bans are held; when full, the one whose netblock has gone longest without a request is dropped first. - Each ban carries the notes "Persistent state" lists, as far as they are known at this stage: the limit, its window and the count reached; the AS number, AS name and country when looked up; the last ten requests that counted toward it, each text cut to 256 bytes; how many requests counted and over what time; the requests refused under it; earlier bans of each kind. The netblock's total since it was first seen comes with the client history in https://git.eeqj.de/sneak/smallwebwaf/issues/17. Memory stays bounded; the PR body says what the notes cost at the default bounds. - `SWWAF_BAN_RESPONSE` (`403`, `429` or `close`) also answers the country lists and `SWWAF_DENY_NETS`, as "Data flow for one request" says. - New settings, each with its default from "Configuration surface": `SWWAF_BAN_RESPONSE`, `SWWAF_LIMIT_BAN_DURATION`, `SWWAF_LIMIT_BAN_REPEAT_WINDOW`, `SWWAF_MAX_BAN_DURATION`, `SWWAF_MAX_BANS`, `SWWAF_BAN_SCOPE_V4_PREFIX`; a value set but invalid stops the start. `README.md` documents them and the change from `429`. Definition of done: tests, on a clock the test controls, show a first ban, the threefold repeats, the permanent ban, the repeat window running out, counters reset by a ban, a banned netblock refused and not counted, the `SWWAF_MAX_BANS` bound dropping the right ban, `SWWAF_BAN_SCOPE_V4_PREFIX`, each `SWWAF_BAN_RESPONSE` value, the notes, the defaults and invalid values; `make check` green; one PR to `next`, passed by a reviewer who did not write it. Model: opus-5-5
clawbot self-assigned this 2026-10-06 01:25:03 +02:00
Author
Collaborator

Built in #69, waiting for review.

Model: opus-5-5

Built in https://git.eeqj.de/sneak/smallwebwaf/pulls/69, waiting for review. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/smallwebwaf#18