ModernUO/Projects/UOContent/Network/AutoDenylist/AutoDenylistConfiguration.cs
Kamron Batman b8b5a1e0c9
docs: tighten the comments across the ban subsystem
Comments only -- no code changed. Covers the blocklist, file allowlist,
login allowlist, auto-denylist, CrowdSec reporter and firewall.

Removes development narration: "(Task 2)" left over from a plan in
Firewall.PurgeExpired, "matching the per-feature JSON config pattern used
by X" repeated across four config loaders, "Recurring and tokenless
before" describing an edit rather than the code, and a duplicated
threading note in BlocklistSnapshot that the inline comment already made.
Points Firewall at dev-docs/ip-bans-and-allowlists.md instead of a
"ban-channel design doc" that does not exist.

Fixes a stale reference the cleanup surfaced: FileAllowlist's remarks
still told readers to opt in via blocklist.json's "allowlistEnabled",
which moved to "enabled" in ip-allowlist.json.

Kept, in tightened form, everything that encodes a reason the code cannot
show: the CrowdSec culture and LAPI protocol notes, why the reporter
flushes off the loop thread at shutdown, why FullMode.Wait rather than
DropWrite, why Firewall reads Core.Now instead of DateTime.UtcNow, and the
volatile-swap contracts on both snapshots.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 21:19:50 -07:00

80 lines
3.3 KiB
C#

/*************************************************************************
* ModernUO *
* Copyright 2019-2026 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AutoDenylistConfiguration.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.IO;
using System.Text.Json.Serialization;
using Server.Json;
namespace Server.Network;
/// <summary>
/// Loads the <see cref="AutoDenylistSettings"/> from <c>Configuration/auto-denylist.json</c>. Loaded once;
/// a missing file writes a template so operators have something to edit.
/// </summary>
public static class AutoDenylistConfiguration
{
private const string _path = "Configuration/auto-denylist.json";
public static AutoDenylistSettings Settings { get; private set; }
public static void Load()
{
var path = Path.Join(Core.BaseDirectory, _path);
if (File.Exists(path))
{
Settings = JsonConfig.Deserialize<AutoDenylistSettings>(path);
}
else
{
Settings = new AutoDenylistSettings();
Save();
}
}
private static void Save()
{
JsonConfig.Serialize(Path.Join(Core.BaseDirectory, _path), Settings);
}
}
/// <summary>Bound configuration for <see cref="AutoDenylist"/>.</summary>
public record AutoDenylistSettings
{
/// <summary>Whether behavioural detections are held locally. Disabled makes the filter inert.</summary>
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
/// <summary>
/// How long an address is denied at accept after the shard catches it misbehaving. Deliberately
/// independent of the duration reported to external bouncers: this is a local holding pen, not a ban.
/// </summary>
/// <remarks>
/// Short on purpose: it covers the gap before an OS bouncer reacts, and blunts a flood on shards running
/// none. An address still attacking is simply re-detected and re-added, so the list sustains itself while
/// a mistake clears on its own.
/// </remarks>
[JsonPropertyName("duration")]
public TimeSpan Duration { get; set; } = TimeSpan.FromMinutes(15);
/// <summary>
/// Hard cap on tracked addresses: a distinct-source flood is the case this exists for, so the cap is what
/// stops it becoming the exhaustion it prevents. At the cap new addresses are not tracked, but are still
/// disconnected by whichever gate detected them.
/// </summary>
[JsonPropertyName("maxEntries")]
public int MaxEntries { get; set; } = 65536;
}