diff --git a/Content.Server/Connection/ConnectionManager.cs b/Content.Server/Connection/ConnectionManager.cs index f22ff9b7d5..d7c3e4cf74 100644 --- a/Content.Server/Connection/ConnectionManager.cs +++ b/Content.Server/Connection/ConnectionManager.cs @@ -1,7 +1,9 @@ using System.Collections.Immutable; +using System.Linq; using System.Runtime.InteropServices; using System.Text.Json.Nodes; using System.Threading.Tasks; +using Content.Server.Chat.Managers; using Content.Server.Database; using Content.Server.GameTicking; using Content.Server.Preferences.Managers; @@ -10,7 +12,9 @@ using Content.Shared.GameTicking; using Content.Shared.Players.PlayTimeTracking; using Robust.Server.Player; using Robust.Shared.Configuration; +using Robust.Shared.Enums; using Robust.Shared.Network; +using Robust.Shared.Player; using Robust.Shared.Timing; /* @@ -50,6 +54,7 @@ namespace Content.Server.Connection [Dependency] private readonly ServerDbEntryManager _serverDbEntry = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly ILogManager _logManager = default!; + [Dependency] private readonly IChatManager _chatManager = default!; private readonly Dictionary _temporaryBypasses = []; private ISawmill _sawmill = default!; @@ -60,6 +65,7 @@ namespace Content.Server.Connection _netMgr.Connecting += NetMgrOnConnecting; _netMgr.AssignUserIdCallback = AssignUserIdCallback; + _plyMgr.PlayerStatusChanged += PlayerStatusChanged; // Approval-based IP bans disabled because they don't play well with Happy Eyeballs. // _netMgr.HandleApprovalCallback = HandleApproval; } @@ -128,6 +134,42 @@ namespace Content.Server.Connection } } + private async void PlayerStatusChanged(object? sender, SessionStatusEventArgs args) + { + if (args.NewStatus == SessionStatus.Connected) + { + AdminAlertIfSharedConnection(args.Session); + } + } + + private void AdminAlertIfSharedConnection(ICommonSession newSession) + { + var playerThreshold = _cfg.GetCVar(CCVars.AdminAlertMinPlayersSharingConnection); + if (playerThreshold < 0) + return; + + var addr = newSession.Channel.RemoteEndPoint.Address; + + var otherConnectionsFromAddress = _plyMgr.Sessions.Where(session => + session.Status is SessionStatus.Connected or SessionStatus.InGame + && session.Channel.RemoteEndPoint.Address.Equals(addr) + && session.UserId != newSession.UserId) + .ToList(); + + var otherConnectionCount = otherConnectionsFromAddress.Count; + if (otherConnectionCount + 1 < playerThreshold) // Add one for the total, not just others, using the address + return; + + var username = newSession.Name; + var otherUsernames = string.Join(", ", + otherConnectionsFromAddress.Select(session => session.Name)); + + _chatManager.SendAdminAlert(Loc.GetString("admin-alert-shared-connection", + ("player", username), + ("otherCount", otherConnectionCount), + ("otherList", otherUsernames))); + } + /* * TODO: Jesus H Christ what is this utter mess of a function * TODO: Break this apart into is constituent steps. diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 1a1a7f0226..ef3615f103 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -832,6 +832,15 @@ namespace Content.Shared.CCVar public static readonly CVarDef ServerBanErasePlayer = CVarDef.Create("admin.server_ban_erase_player", false, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + /// + /// Minimum players sharing a connection required to create an alert. -1 to disable the alert. + /// + /// + /// If you set this to 0 or 1 then it will alert on every connection, so probably don't do that. + /// + public static readonly CVarDef AdminAlertMinPlayersSharingConnection = + CVarDef.Create("admin.alert.min_players_sharing_connection", -1, CVar.SERVERONLY); + /// /// Minimum explosion intensity to create an admin alert message. -1 to disable the alert. /// diff --git a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml index 46e53c0c88..807b21b469 100644 --- a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml +++ b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml @@ -36,6 +36,7 @@ limit = 10.0 see_own_notes = true deadmin_on_join = true new_player_threshold = 600 +alert.min_players_sharing_connection = 2 [worldgen] enabled = true diff --git a/Resources/Locale/en-US/administration/admin-alerts.ftl b/Resources/Locale/en-US/administration/admin-alerts.ftl new file mode 100644 index 0000000000..40ab4737dc --- /dev/null +++ b/Resources/Locale/en-US/administration/admin-alerts.ftl @@ -0,0 +1 @@ +admin-alert-shared-connection = {$player} is sharing a connection with {$otherCount} connected player(s): {$otherList}