fix: actually working ban functionality

Changes:
- ignore new sockets from banned IP addresses way earlier.
- ignore all packets by banned profiles.

Intentionally keeping the connection open instead of d/c banned clients.
This is to prevent endless server logs due to automatically reconnecting clients.

Before:
Reconnecting clients aren't entering `ClientJoined` and therefore the d/c is only working on first connections.
Effectively banned clients got a d/c and then automatically reconnected again without getting a d/c again.
Therefore allowing them to play normally.
This commit is contained in:
Robin C. Ladiges 2023-03-23 01:16:11 +01:00
parent 6bbce7a52a
commit 11c291c105
No known key found for this signature in database
GPG Key ID: B494D3DF92661B99
4 changed files with 23 additions and 4 deletions

View File

@ -128,6 +128,7 @@ public static class BanLists {
public static void Crash(Client user, bool permanent = false) {
user.Ignored = true;
Task.Run(async () => {
await user.Send(new ChangeStagePacket {
Id = (permanent ? "$agogus/ban4lyfe" : "$among$us/cr4sh%"),

View File

@ -12,6 +12,7 @@ namespace Server;
public class Client : IDisposable {
public readonly ConcurrentDictionary<string, object?> Metadata = new ConcurrentDictionary<string, object?>(); // can be used to store any information about a player
public bool Connected = false;
public bool Ignored = false;
public CostumePacket? CurrentCostume = null; // required for proper client sync
public string Name {
get => Logger.Name;

View File

@ -62,9 +62,6 @@ async Task LoadShines()
await LoadShines();
server.ClientJoined += (c, _) => {
if (BanLists.Enabled && BanLists.IsClientBanned(c)) {
throw new Exception($"Banned player attempted join: {c.Name}");
}
c.Metadata["shineSync"] = new ConcurrentBag<int>();
c.Metadata["loadedSave"] = false;
c.Metadata["scenario"] = (byte?) 0;

View File

@ -29,6 +29,11 @@ public class Server {
Socket socket = token.HasValue ? await serverSocket.AcceptAsync(token.Value) : await serverSocket.AcceptAsync();
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
if (BanLists.Enabled && BanLists.IsIPv4Banned(((IPEndPoint) socket.RemoteEndPoint!).Address!)) {
Logger.Warn($"Ignoring banned IPv4 address {socket.RemoteEndPoint}");
continue;
}
Logger.Warn($"Accepted connection for client {socket.RemoteEndPoint}");
try {
@ -64,7 +69,7 @@ public class Server {
public static void FillPacket<T>(PacketHeader header, T packet, Memory<byte> memory) where T : struct, IPacket {
Span<byte> data = memory.Span;
header.Serialize(data[..Constants.HeaderSize]);
packet.Serialize(data[Constants.HeaderSize..]);
}
@ -167,6 +172,11 @@ public class Server {
break;
}
if (client.Ignored) {
memory.Dispose();
continue;
}
// connection initialization
if (first) {
first = false;
@ -174,6 +184,16 @@ public class Server {
ConnectPacket connect = new ConnectPacket();
connect.Deserialize(memory.Memory.Span[packetRange]);
if (BanLists.Enabled && BanLists.IsProfileBanned(header.Id)) {
client.Id = header.Id;
client.Name = connect.ClientName;
client.Ignored = true;
client.Logger.Warn($"Ignoring banned profile ID {header.Id}");
memory.Dispose();
continue;
}
lock (Clients) {
if (Clients.Count(x => x.Connected) == Settings.Instance.Server.MaxPlayers) {
client.Logger.Error($"Turned away as server is at max clients");