From b23441192af6ddfc2cdd688b8f15cf0d84e235ad Mon Sep 17 00:00:00 2001 From: RavMorgan <48182970+RavMorgan@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:40:04 +0300 Subject: [PATCH] SALUS (#464) Co-authored-by: Mona Hmiza --- .../Administration/UI/Tabs/ServerTab.xaml | 1 + Content.Server/Entry/EntryPoint.cs | 1 + Content.Server/IoC/ServerContentIoC.cs | 2 + Content.Server/White/Salus/SalusCommand.cs | 48 +++++++++++++++ Content.Server/White/Salus/SalusManager.cs | 60 +++++++++++++++++++ Content.Shared/White/WhiteCVars.cs | 5 ++ Resources/Locale/en-US/white/salus.ftl | 9 +++ Resources/Locale/ru-RU/white/salus.ftl | 9 +++ 8 files changed, 135 insertions(+) create mode 100644 Content.Server/White/Salus/SalusCommand.cs create mode 100644 Content.Server/White/Salus/SalusManager.cs create mode 100644 Resources/Locale/en-US/white/salus.ftl create mode 100644 Resources/Locale/ru-RU/white/salus.ftl diff --git a/Content.Client/Administration/UI/Tabs/ServerTab.xaml b/Content.Client/Administration/UI/Tabs/ServerTab.xaml index 13d1969559..73628c3557 100644 --- a/Content.Client/Administration/UI/Tabs/ServerTab.xaml +++ b/Content.Client/Administration/UI/Tabs/ServerTab.xaml @@ -10,5 +10,6 @@ + diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index 7e3f9c1f35..54d9b4f893 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -117,6 +117,7 @@ namespace Content.Server.Entry IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); //WD-EDIT _voteManager.Initialize(); diff --git a/Content.Server/IoC/ServerContentIoC.cs b/Content.Server/IoC/ServerContentIoC.cs index 5851d2651a..821048bd22 100644 --- a/Content.Server/IoC/ServerContentIoC.cs +++ b/Content.Server/IoC/ServerContentIoC.cs @@ -20,6 +20,7 @@ using Content.Server.ServerUpdates; using Content.Server.Voting.Managers; using Content.Server.Worldgen.Tools; using Content.Server.UtkaIntegration; +using Content.Server.White; using Content.Server.White.JoinQueue; using Content.Server.White.Jukebox; using Content.Server.White.Sponsors; @@ -73,6 +74,7 @@ namespace Content.Server.IoC IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); // WD-EDIT } } diff --git a/Content.Server/White/Salus/SalusCommand.cs b/Content.Server/White/Salus/SalusCommand.cs new file mode 100644 index 0000000000..1438b78180 --- /dev/null +++ b/Content.Server/White/Salus/SalusCommand.cs @@ -0,0 +1,48 @@ +using Content.Server.Administration; +using Content.Server.Chat.Managers; +using Content.Shared.Administration; +using Content.Shared.White; +using Robust.Shared.Configuration; +using Robust.Shared.Console; + +namespace Content.Server.White; + +[AdminCommand(AdminFlags.Admin)] +public sealed class SalusCommand : IConsoleCommand +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public string Command => "salus"; + public string Description => "Enables SALUS system (Autokick vpn users)"; + public string Help => "salus or salus for toggle on/off"; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + IoCManager.InjectDependencies(this); + + if (args.Length > 1) + { + shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1))); + return; + } + + var enabled = _cfg.GetCVar(WhiteCVars.AutoKickVpnUsers); + + if (args.Length == 0) + { + enabled = !enabled; + } + + if (args.Length == 1 && !bool.TryParse(args[0], out enabled)) + { + shell.WriteError(Loc.GetString("shell-argument-must-be-boolean")); + return; + } + + _cfg.SetCVar(WhiteCVars.AutoKickVpnUsers, enabled); + + var announce = Loc.GetString("vpn-salus-status", ("enabled", $"{enabled}")); + + IoCManager.Resolve().DispatchServerAnnouncement(announce, Color.Red); + } +} diff --git a/Content.Server/White/Salus/SalusManager.cs b/Content.Server/White/Salus/SalusManager.cs new file mode 100644 index 0000000000..a2e71e4617 --- /dev/null +++ b/Content.Server/White/Salus/SalusManager.cs @@ -0,0 +1,60 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Content.Server.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.White; +using Robust.Shared.Configuration; +using Robust.Shared.Network; + +namespace Content.Server.White; + +public sealed class SalusManager +{ + [Dependency] private readonly IServerNetManager _netMgr = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; + + private readonly HttpClient _httpClient = new(); + + private bool _autoKickVpnUsers; + private string _salusApiLink = default!; + + public void Initialize() + { + _httpClient.Timeout = TimeSpan.FromSeconds(2.5); + _cfg.OnValueChanged(WhiteCVars.AutoKickVpnUsers, newValue => _autoKickVpnUsers = newValue, true); + _cfg.OnValueChanged(WhiteCVars.SalusApiLink, newValue => _salusApiLink = newValue, true); + + _netMgr.Connecting += OnConnecting; + } + + private async Task OnConnecting(NetConnectingArgs arg) + { + var ip = arg.IP.Address.ToString(); + bool usingVpn; + + try + { + var response = await _httpClient.GetAsync($"{_salusApiLink}{ip}"); + if (response.StatusCode != HttpStatusCode.OK) return; + usingVpn = bool.Parse(await response.Content.ReadAsStringAsync()); + + } + catch (Exception e) + { + return; + } + + if (usingVpn) + { + var logMessage = Loc.GetString("vpn-user-detected", ("user", arg.UserName), ("ip", ip)); + _adminLogger.Add(LogType.Unknown, LogImpact.Extreme, $"{logMessage}"); + + if (_autoKickVpnUsers) + { + arg.Deny(Loc.GetString("vpn-user-disconnect-message")); + } + } + } +} diff --git a/Content.Shared/White/WhiteCVars.cs b/Content.Shared/White/WhiteCVars.cs index 0da1914bbb..8e0d179224 100644 --- a/Content.Shared/White/WhiteCVars.cs +++ b/Content.Shared/White/WhiteCVars.cs @@ -325,4 +325,9 @@ public sealed class WhiteCVars public static readonly CVarDef DamageGetModifier = CVarDef.Create("damage.get_modifier", 1.0f, CVar.REPLICATED); + public static readonly CVarDef AutoKickVpnUsers = + CVarDef.Create("white.auto_kick_vpn_users", false, CVar.SERVERONLY); + + public static readonly CVarDef SalusApiLink = CVarDef.Create("white.salus_api_link", "http://localhost:7100/vpnchecker?address=", CVar.SERVERONLY | CVar.CONFIDENTIAL); + } diff --git a/Resources/Locale/en-US/white/salus.ftl b/Resources/Locale/en-US/white/salus.ftl new file mode 100644 index 0000000000..f33b58a21e --- /dev/null +++ b/Resources/Locale/en-US/white/salus.ftl @@ -0,0 +1,9 @@ +vpn-user-detected = Attention, a prankster came in under the vpn { $user }. IP: { $ip } +vpn-user-disconnect-message = It is forbidden to play through VPN on the server. +vpn-salus-button = Toggle SALUS +vpn-salus-status = + { $enabled -> + [True] Guests hiding their faces behind masks are not allowed to enter + [False] Guests hiding their face behind masks are allowed to enter. + *[other] Яниме + } diff --git a/Resources/Locale/ru-RU/white/salus.ftl b/Resources/Locale/ru-RU/white/salus.ftl new file mode 100644 index 0000000000..c68fd46437 --- /dev/null +++ b/Resources/Locale/ru-RU/white/salus.ftl @@ -0,0 +1,9 @@ +vpn-user-detected = Внимание, пытается зайти приколист под впном { $user }. Айпи: { $ip } +vpn-user-disconnect-message = На сервере запрещена игра через ВПН. +vpn-salus-button = Переключить SALUS +vpn-salus-status = + { $enabled -> + [True] Гостям скрывающим свое лицо за масками вход запрещен. + [False] Гостям скрывающим свое лицо за масками вход разрешен. + *[other] Яниме + }