]> git.deb.at Git - rhonda/impostor.git/commitdiff
Added an RPC packet size anti-cheat check with config (#731)
authorChristina <122680126+HayashiUme@users.noreply.github.com>
Sun, 21 Jun 2026 09:17:05 +0000 (17:17 +0800)
committerGitHub <noreply@github.com>
Sun, 21 Jun 2026 09:17:05 +0000 (11:17 +0200)
* Added an RPC packet size anti-cheat

* Support PackedGameDataTo

* Move packet size check to HazelConnection

* Update PacketSizeLimit to 1153 and add anti-cheat docs

* Change default to value determined on officials

Thanks Niko for doing the research
---------

Co-authored-by: miniduikboot <mini@duikbo.at>
Co-authored-by: NikoCat233 <139348239+NikoCat233@users.noreply.github.com>
docs/Server-configuration.md
src/Impostor.Api/CheatCategory.cs
src/Impostor.Api/Config/AntiCheatConfig.cs
src/Impostor.Server/Net/Client.cs
src/Impostor.Server/Net/Hazel/HazelConnection.cs
src/Impostor.Server/Net/Matchmaker.cs
src/Impostor.Server/config.json

index 61891296698a4eb7a25fcf4accba0ab3eed112a2..6252b981bbdf3568ecbd7be43eb850df150f60ee 100644 (file)
@@ -40,6 +40,8 @@ Impostor has an Anticheat that makes it possible to kick cheaters from games aut
 | **EnableRoleChecks**          | `true`        | Enables checks that check if players have the correct role when performing certain role abilities like venting or murdering.                                                                                        |
 | **EnableTargetChecks**        | `true`        | Enables checks that check if certain packets to everyone that should only have been sent to certain players or vice versa. This includes sending votes or network objects.                                          |
 | **ForbidProtocolExtensions**  | `true`        | If disabled allows players to send network packets that go beyond the network packets sent by the vanilla game. This is necessary for most mods that need all players to install it.                                |
+| **EnablePacketSizeChecks**    | `true`        | Enables checks that verify if network messages exceed the maximum allowed size.                                                                                                                                     |
+| **PacketSizeLimit**           | `1203`        | The maximum allowed size (in bytes) for a network message. The official servers of Among Us requires that a Hazel packet is < 1204 bytes, excluding headers.                                                        |
 
 ### Compatibility
 
index 26f6c5a67cb618d8747e9ba21b14ced3dbb70b21..5b890060b267729449d5933e89e9ce7c3c85809c 100644 (file)
@@ -32,6 +32,9 @@ public enum CheatCategory
     /// <summary>A packet was sent on an invalid network object, like a PlayerControl without PlayerInfo.</summary>
     InvalidObject,
 
+    /// <summary>A packet was sent that exceeded the maximum allowed RPC size.</summary>
+    PacketSize,
+
     /// <summary>Legacy category for unsorted anticheat checks.</summary>
     Other,
 }
index a649904052c5337684c83c3613bcf7a6f7558454..a92330687ca752b868deecfced995db731bcef7b 100644 (file)
@@ -29,5 +29,9 @@ namespace Impostor.Api.Config
         public bool EnableTargetChecks { get; set; } = true;
 
         public bool ForbidProtocolExtensions { get; set; } = true;
+
+        public bool EnablePacketSizeChecks { get; set; } = true;
+
+        public int PacketSizeLimit { get; set; } = 1203;
     }
 }
index 08597c22c39e241fa346c3e71a24d1aaa083a491..65d8e4960f0dfb434b4caa3f9ab6c4e43b1c70cc 100644 (file)
@@ -80,6 +80,7 @@ namespace Impostor.Server.Net
                     CheatingHostMode.Never => true,
                     _ => true,
                 },
+                CheatCategory.PacketSize => _antiCheatConfig.EnablePacketSizeChecks,
                 CheatCategory.Other => true,
                 _ => LogUnknownCategory(category),
             };
index 47c094f465f649f6b7cd3466d8e52dac08852dc1..3033cfb1256c5b73f3809e60d6128b83330a6f0b 100644 (file)
@@ -1,18 +1,23 @@
 using System.Net;
 using System.Threading.Tasks;
+using Impostor.Api;
+using Impostor.Api.Config;
 using Impostor.Api.Net;
 using Impostor.Hazel;
 using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
 
 namespace Impostor.Server.Net.Hazel
 {
     internal class HazelConnection : IHazelConnection
     {
         private readonly ILogger<HazelConnection> _logger;
+        private readonly AntiCheatConfig _antiCheatConfig;
 
-        public HazelConnection(Connection innerConnection, ILogger<HazelConnection> logger)
+        public HazelConnection(Connection innerConnection, ILogger<HazelConnection> logger, IOptions<AntiCheatConfig> antiCheatOptions)
         {
             _logger = logger;
+            _antiCheatConfig = antiCheatOptions.Value;
             InnerConnection = innerConnection;
             innerConnection.DataReceived = ConnectionOnDataReceived;
             innerConnection.Disconnected = ConnectionOnDisconnected;
@@ -58,6 +63,19 @@ namespace Impostor.Server.Net.Hazel
                 return;
             }
 
+            // Check raw message size against the configured limit.
+            // Innersloth requires full packet ≤ 1200 bytes (1168 bytes payload after 32 bytes IP+UDP headers).
+            if (e.Message.Length > _antiCheatConfig.PacketSizeLimit)
+            {
+                if (await Client.ReportCheatAsync(
+                        new CheatContext("RootMessage"),
+                        CheatCategory.PacketSize,
+                        $"Received a message that is too large, length: {e.Message.Length}"))
+                {
+                    return;
+                }
+            }
+
             while (true)
             {
                 if (e.Message.Position >= e.Message.Length)
index a8682bf69d447f42229a7bfc178c1dfe38f53ecd..55b76ea6b85ea2915e2408b20fab1de4b4e87853 100644 (file)
@@ -2,6 +2,7 @@
 using System.Net;
 using System.Net.Sockets;
 using System.Threading.Tasks;
+using Impostor.Api.Config;
 using Impostor.Api.Events.Managers;
 using Impostor.Api.Net.Messages.C2S;
 using Impostor.Hazel;
@@ -11,6 +12,7 @@ using Impostor.Server.Net.Hazel;
 using Impostor.Server.Net.Manager;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.ObjectPool;
+using Microsoft.Extensions.Options;
 
 namespace Impostor.Server.Net
 {
@@ -20,18 +22,21 @@ namespace Impostor.Server.Net
         private readonly ClientManager _clientManager;
         private readonly ObjectPool<MessageReader> _readerPool;
         private readonly ILogger<HazelConnection> _connectionLogger;
+        private readonly IOptions<AntiCheatConfig> _antiCheatOptions;
         private UdpConnectionListener? _connection;
 
         public Matchmaker(
             IEventManager eventManager,
             ClientManager clientManager,
             ObjectPool<MessageReader> readerPool,
-            ILogger<HazelConnection> connectionLogger)
+            ILogger<HazelConnection> connectionLogger,
+            IOptions<AntiCheatConfig> antiCheatOptions)
         {
             _eventManager = eventManager;
             _clientManager = clientManager;
             _readerPool = readerPool;
             _connectionLogger = connectionLogger;
+            _antiCheatOptions = antiCheatOptions;
         }
 
         public async ValueTask StartAsync(IPEndPoint ipEndPoint)
@@ -64,7 +69,7 @@ namespace Impostor.Server.Net
             // Handshake.
             HandshakeC2S.Deserialize(e.HandshakeData, out var clientVersion, out var name, out var language, out var chatMode, out var platformSpecificData);
 
-            var connection = new HazelConnection(e.Connection, _connectionLogger);
+            var connection = new HazelConnection(e.Connection, _connectionLogger, _antiCheatOptions);
 
             await _eventManager.CallAsync(new ClientConnectionEvent(connection, e.HandshakeData));
 
index 68d2dc97b5fa281e7331a953b56e541f336052b9..cdd37908f5992f15099360882f1dff2a8c78ff14 100644 (file)
@@ -21,7 +21,9 @@
     "EnableOwnershipChecks": true,
     "EnableRoleChecks": true,
     "EnableTargetChecks": true,
-    "ForbidProtocolExtensions": true
+    "ForbidProtocolExtensions": true,
+    "EnablePacketSizeChecks": true,
+    "PacketSizeLimit": 1203
   },
   "Timeout": {
     "SpawnTimeout": 2500,