/************************************************************************* * ModernUO * * Copyright 2019-2026 - ModernUO Development Team * * Email: hi@modernuo.com * * File: LoginAllowlistConfiguration.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/login-allowlist.json (matching /// the per-feature JSON config pattern used by BlocklistConfiguration). Loaded once; a missing file /// writes a template so operators have something to edit. /// public static class LoginAllowlistConfiguration { private const string _path = "Configuration/login-allowlist.json"; public static LoginAllowlistSettings 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 LoginAllowlistSettings(); Save(); } } private static void Save() { JsonConfig.Serialize(Path.Join(Core.BaseDirectory, _path), Settings); } } /// /// Bound configuration for : which addresses have recently proven they carry a /// real player, how long that proof counts, and how much misbehaviour revokes it. /// /// /// The recency window is the point. Consumer addresses are reassigned constantly, and on CGNAT the same /// address fronts a different subscriber week to week, so a list without a TTL becomes a list of strangers. /// public record LoginAllowlistSettings { /// Whether successful logins are recorded and consulted at all. Disabled makes the list inert. [JsonPropertyName("enabled")] public bool Enabled { get; set; } = true; /// /// Where the list is persisted. A relative path resolves against . /// Plain text, one address unix-seconds pair per line, so it can be read and edited by hand. /// Set to "" to disable. /// [JsonPropertyName("file")] public string File { get; set; } = "Configuration/login-allowlist.txt"; /// /// How long a successful login allowlists its address; dropped on the next flush after that. 90 days /// covers a player who takes a season off without carrying a reassigned address indefinitely. /// [JsonPropertyName("ttl")] public TimeSpan Ttl { get; set; } = TimeSpan.FromDays(90); /// /// How often a changed list is written out. A crash loses at most this much, and an entry is re-earned by /// the next login. /// [JsonPropertyName("flushInterval")] public TimeSpan FlushInterval { get; set; } = TimeSpan.FromMinutes(1); /// /// How many suppressed contributions inside revoke an address's entry. Past /// this it escalates like anything else until it earns a new entry by logging in again. /// /// /// Generous on purpose: local defences never stop applying, so a high threshold only delays the external /// ban. A bad line might trip a gate a few times an hour; a host being used to flood burns through this /// in seconds. Set to 0 to never revoke. /// [JsonPropertyName("escalateAfterStrikes")] public int EscalateAfterStrikes { get; set; } = 10; /// Rolling window the strike count is measured over. A quiet hour clears the tally. [JsonPropertyName("strikeWindow")] public TimeSpan StrikeWindow { get; set; } = TimeSpan.FromHours(1); }