docs: record the auto-denylist behaviour changes

Three gaps the review missed, docs only.

A hold is no longer extended by repeat detections, which is operator-
visible: an address that keeps trying is now released 15 minutes after its
FIRST detection rather than held indefinitely. Someone debugging why an
address came back needs to know that, and that the rate limiter re-holds it
on the next attempt rather than letting it through free.

Nothing described what happens at maxEntries. Past the cap a detection
still disconnects but is not held, so the address pays full detection cost
per reconnect. Added to Known limits next to the MaxConnections ceiling,
since both end in the same place: a flood past it wants upstream scrubbing,
not a larger cap that only buys a longer on-loop scan.

networking-packets.md listed the three shipping filters without noting the
blocklist is now opt-in.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-08-13 23:09:22 -07:00
parent 5b7304addd
commit 5501c922ca
No known key found for this signature in database
GPG key ID: 7D81DF26D9A5D94A
2 changed files with 13 additions and 3 deletions

View file

@ -163,6 +163,12 @@ Escalation is **immediate**, on the first detection: a 15-minute local hold plus
(4h) contribution. There is no N-connection threshold; the strike counter governs only revoking a
`LoginAllowlist` entry.
The local hold runs 15 minutes from the **first** detection and is never extended by later ones, so an
address that keeps trying is released on schedule rather than held indefinitely. It does not get a free
run: the rate limiter sits *ahead* of the connection filters, so a flooder is re-reported and re-held on
its next attempt. Not refreshing is what keeps the holds in expiry order, which is what makes retiring
lapsed ones cost the number expiring rather than the number held.
### What is deliberately NOT detected
**Do not add rules based on arrival framing.** TCP has no message boundaries, so the network, the OS or a
@ -192,6 +198,10 @@ firewalled off. Shortening the 5s handshake window has been tried and broke real
- **`MaxConnections` (4096) is a hard ceiling.** The accept gate runs *after* the kernel completed the TCP
handshake, so a blocklist match saves the socket setup and the `NetState` slot but never the connection
itself. Only an upstream L4 proxy or edge scrubbing moves that cost off the shard.
- **The `auto-denylist` stops tracking at `maxEntries`.** Past it a detection still disconnects the
connection, but the address is not held, so it pays full detection cost on every reconnect instead of a
cheap accept-gate deny. The default is sized for the 50k250k distinct-source floods seen in practice; a
flood past it wants upstream scrubbing rather than a larger cap, which only buys a longer on-loop scan.
## Configuration

View file

@ -511,9 +511,9 @@ Rules:
Core owns the question; **every implementation lives in UOContent**. The three that ship are `firewall`
(admin-curated, mutable at runtime, persisted to `Configuration/firewall.json`), `blocklist` (file-sourced,
millions of entries, demand-pages hits to CrowdSec) and `auto-denylist` (in-memory, short-lived, fed by the
shard's own behavioural detections). A shard that fronts its server with an upstream proxy or edge scrubbing
can drop all of them and register nothing.
millions of entries, demand-pages hits to CrowdSec, **opt-in**) and `auto-denylist` (in-memory,
short-lived, fed by the shard's own behavioural detections). A shard that fronts its server with an
upstream proxy or edge scrubbing can drop all of them and register nothing.
The allowlists, ban contribution, behavioural detection and the operator process for exempting a
false-positive address are covered separately in