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] Яниме
+ }