feat: dedicated server security hardening
Comprehensive security system to protect against packet-sniffing attacks, XUID harvesting, privilege escalation, bot flooding, and XUID impersonation. - Stream cipher: per-session XOR cipher with 4-message handshake via CustomPayloadPacket (MC|CKey, MC|CAck, MC|COn). Negotiated per-connection, backwards compatible (old clients/servers fall back to plaintext). - Security gate: buffers all game data until cipher handshake completes, preventing unsecured clients from receiving any XUIDs or game state. - Cipher handshake enforcer: kicks clients that don't complete the handshake within 5 seconds (configurable via require-secure-client). - Identity tokens: persistent per-XUID tokens in identity-tokens.json, issued over the encrypted channel, verified on reconnect. Prevents XUID replay attacks. Client stores server-specific tokens. - PROXY protocol v1: parses real client IPs from playit.gg tunnel headers so rate limiting, IP bans, and XUID spoof detection work per-player. - Rate limiting: per-IP sliding window (default 5 connections/30s) with pending connection cap (default 10). - Privilege hardening: OP requires ops.json, live checks on every command and privilege packet. Host-only server settings changes. - XUID stripping: PreLoginPacket response sends INVALID_XUID placeholders. - Packet validation: readUtf global string cap, reduced max packet size, stream desync protection on oversized strings. - OpManager: persistent ops.json with XUID-based OP list. - Whitelist improvements: whitelist add accepts player names with ambiguity detection, XUID cache from login attempts. - revoketoken command: revoke identity tokens for players who lost theirs. - server.log: persistent log file written alongside console output with flush-per-write to survive crashes. - CLI security logging: consolidated per-join security summary with cipher status, token status, XUID, and real IP. Security warnings for kicks, spoofing, and unauthorized commands.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
#include "..\..\Common\Network\NetworkPlayerInterface.h"
|
||||
#include "..\..\..\Minecraft.World\DisconnectPacket.h"
|
||||
#include "..\..\..\Minecraft.Server\Security\StreamCipher.h"
|
||||
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
|
||||
@@ -16,7 +17,7 @@
|
||||
#define WIN64_NET_MAX_CLIENTS 255
|
||||
#define WIN64_SMALLID_REJECT 0xFF
|
||||
#define WIN64_NET_RECV_BUFFER_SIZE 65536
|
||||
#define WIN64_NET_MAX_PACKET_SIZE (4 * 1024 * 1024)
|
||||
#define WIN64_NET_MAX_PACKET_SIZE (512 * 1024)
|
||||
#define WIN64_LAN_DISCOVERY_PORT 25566
|
||||
#define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E
|
||||
|
||||
@@ -190,8 +191,38 @@ private:
|
||||
static BYTE s_splitScreenSmallId[XUSER_MAX_COUNT];
|
||||
static HANDLE s_splitScreenRecvThread[XUSER_MAX_COUNT];
|
||||
|
||||
// Client-side stream cipher (non-host only, one connection to server)
|
||||
static ServerRuntime::Security::StreamCipher s_clientSendCipher;
|
||||
static ServerRuntime::Security::StreamCipher s_clientRecvCipher;
|
||||
static CRITICAL_SECTION s_clientCipherLock;
|
||||
static uint8_t s_clientPendingKey[ServerRuntime::Security::StreamCipher::KEY_SIZE];
|
||||
static bool s_clientKeyStored; // protected by s_clientCipherLock
|
||||
|
||||
public:
|
||||
static void ClearSocketForSmallId(BYTE smallId);
|
||||
|
||||
/** Store the cipher key received from the server. Does not activate yet. */
|
||||
static void StoreClientCipherKey(const uint8_t key[ServerRuntime::Security::StreamCipher::KEY_SIZE]);
|
||||
|
||||
/** Send MC|CAck directly to socket then activate client send cipher. Atomic under s_sendLock. */
|
||||
static bool SendAckAndActivateClientSendCipher();
|
||||
|
||||
/** Activate client recv cipher. Called from ClientRecvThreadProc on MC|COn detection. */
|
||||
static void ActivateClientRecvCipher();
|
||||
|
||||
/** Reset client ciphers on disconnect. */
|
||||
static void ResetClientCipher();
|
||||
|
||||
/**
|
||||
* Encrypt data in-place for client->server send if the client send cipher is active.
|
||||
* Returns true if data was encrypted. Thread-safe.
|
||||
*/
|
||||
static bool TryEncryptClientOutgoing(uint8_t *data, int length);
|
||||
|
||||
#if defined(MINECRAFT_SERVER_BUILD)
|
||||
/** Atomically send MC|COn plaintext then commit server cipher. Called from RecvThreadProc. */
|
||||
static bool SendCOnAndCommitServerCipher(BYTE smallId);
|
||||
#endif
|
||||
};
|
||||
|
||||
extern bool g_Win64MultiplayerHost;
|
||||
|
||||
Reference in New Issue
Block a user