Added an RPC packet size anti-cheat check with config (#731)

* 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>
This commit is contained in:
authored and GitHub committed 2026-06-21 11:17:05 +02:00
1 parent e9437e781b
commit 2cad4ffa14
7 files changed
+39 -4

No files matched your search

+2
View 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
+3
View 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,
}
@@ -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;
}
}
+1
View File
@@ -80,6 +80,7 @@ namespace Impostor.Server.Net
CheatingHostMode.Never => true,
_ => true,
},
CheatCategory.PacketSize => _antiCheatConfig.EnablePacketSizeChecks,
CheatCategory.Other => true,
_ => LogUnknownCategory(category),
};
@@ -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)
+7 -2
View 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));
+3 -1
View File
@@ -21,7 +21,9 @@
"EnableOwnershipChecks": true,
"EnableRoleChecks": true,
"EnableTargetChecks": true,
"ForbidProtocolExtensions": true
"ForbidProtocolExtensions": true,
"EnablePacketSizeChecks": true,
"PacketSizeLimit": 1203
},
"Timeout": {
"SpawnTimeout": 2500,