From 5501c922ca2cadbf3df97f4c734c35f54a14a8bd Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:09:22 -0700 Subject: [PATCH] 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) --- dev-docs/ip-bans-and-allowlists.md | 10 ++++++++++ dev-docs/networking-packets.md | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dev-docs/ip-bans-and-allowlists.md b/dev-docs/ip-bans-and-allowlists.md index c0db9dfa4..40320efe5 100644 --- a/dev-docs/ip-bans-and-allowlists.md +++ b/dev-docs/ip-bans-and-allowlists.md @@ -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 50k–250k 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 diff --git a/dev-docs/networking-packets.md b/dev-docs/networking-packets.md index af47a1e06..639963cfd 100644 --- a/dev-docs/networking-packets.md +++ b/dev-docs/networking-packets.md @@ -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