Commit graph

2 commits

Author SHA1 Message Date
Kamron Batman
464d4b7f66
feat(bans): blocklist generator script and a default blocklist location
Adds tools/Export-IpBlocklist.ps1, the producer half of the in-app blocklist
gate. It merges a thin, non-overlapping set of public IP threat feeds into one
de-duplicated, bogon-filtered list and writes the plain-text file the shard
reads via `blocklistFile`. Parsing is done in a compiled Add-Type hot loop
because the anchor feed alone is ~4M lines; the output is streamed so millions
of entries never become millions of strings.

The file is written to a .tmp sibling and swapped with File.Replace, so the
shard never observes a half-written list, and a total feed outage refuses to
overwrite a good list with an empty one. Re-running is idempotent: the script
exits without downloading anything while the list on disk is younger than
-MinInterval (default 2h, the anchor feed's own refresh period), so a
misconfigured scheduler cannot hammer the upstream feeds. Age comes from the
`generated=` header the script writes, falling back to mtime, so no sidecar
state file is needed. -Force overrides.

`blocklistFile` now defaults to Configuration/ip-blocklist.txt instead of being
empty. The gate stays inert while that file is absent, so this is a no-op for
shards that never run the generator, and dropping the file in later is picked
up by the existing poll with no restart.

Two fixes this exposed:

- FileBlocklist used the configured path verbatim despite documenting it as
  relative to Core.BaseDirectory, so a relative path resolved against the
  process working directory. Relative paths now resolve against BaseDirectory;
  absolute paths are honored so several shards can share one generated list.
- A missing file is now the shipped default rather than a misconfiguration, so
  boot logs "inert: no blocklist at ..." instead of "loaded 0 entries".

tools/ stays ignored except for this script.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 00:40:46 -07:00
Kamron Batman
de3cfa35b1
feat(bans): Windows blocklist gate with demand-paged promotion
Enforce a millions-strong external IP blocklist in-app so the OS firewall
never has to hold it (Windows BFE can't). FileBlocklist loads a versioned
file into an immutable SortedRangeIndex snapshot off the game loop (yields to
world saves) and swaps it atomically; the accept path gates against it after
the manual-ban check and, once per suppression window (PromotedGuard),
promotes the hit to CrowdSec (scenario modernuo/blocklist) so the OS bouncer
kernel-drops repeat traffic. The bulk list is produced entirely out-of-process.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 20:38:04 -07:00