/************************************************************************* * 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 . * *************************************************************************/ using System; using System.IO; using System.Text.Json.Serialization; using Server.Json; namespace Server.Network; /// /// Loads the from Configuration/auto-denylist.json. Loaded once; /// a missing file writes a template so operators have something to edit. /// 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(path); } else { Settings = new AutoDenylistSettings(); Save(); } } private static void Save() { JsonConfig.Serialize(Path.Join(Core.BaseDirectory, _path), Settings); } } /// Bound configuration for . public record AutoDenylistSettings { /// Whether behavioural detections are held locally. Disabled makes the filter inert. [JsonPropertyName("enabled")] public bool Enabled { get; set; } = true; /// /// 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. /// /// /// 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. /// [JsonPropertyName("duration")] public TimeSpan Duration { get; set; } = TimeSpan.FromMinutes(15); /// /// 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. /// /// /// A HashSet capacity, not a round number. Grown from empty it steps 36,353 → 75,431 → 156,437 /// → 324,449, so this fills one exactly instead of stranding slots: 65,536 sat just past a resize and /// left 9,895 of them unusable. Sized to cover the 50k–250k distinct-source floods seen in practice, /// for ~19 MB — 36 bytes a set slot plus 24 for the ring record. Raising it is bounded by memory /// rather than by a scan, since holds are retired from the ring in expiry order; a flood past it wants /// upstream scrubbing rather than a larger cap. /// [JsonPropertyName("maxEntries")] public int MaxEntries { get; set; } = 324_449; }