From 46121d6ccfc2c80ec7a608172e7d6feab9c3ec02 Mon Sep 17 00:00:00 2001 From: Razish Date: Sun, 11 Feb 2024 02:23:36 +1100 Subject: [PATCH 1/3] hoist antiFakePlayer code into the server executable - replace g_antiFakePlayer -> sv_antiFakePlayer (1, 2) - replace g_maxConnPerIP -> sv_maxConnPerIP --- codemp/game/g_client.c | 32 -------------------------------- codemp/game/g_xcvar.h | 2 -- codemp/qcommon/q_shared.h | 2 -- codemp/server/server.h | 2 ++ codemp/server/sv_client.cpp | 18 ++++++++++++++++++ codemp/server/sv_init.cpp | 2 ++ codemp/server/sv_main.cpp | 2 ++ 7 files changed, 24 insertions(+), 36 deletions(-) diff --git a/codemp/game/g_client.c b/codemp/game/g_client.c index a46845ddb5..2867f50d5e 100644 --- a/codemp/game/g_client.c +++ b/codemp/game/g_client.c @@ -2451,38 +2451,6 @@ char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot ) { } } - if ( !isBot && firstTime ) - { - if ( g_antiFakePlayer.integer ) - {// patched, check for > g_maxConnPerIP connections from same IP - int count=0, i=0; - for ( i=0; ipers.connected = CON_DISCONNECTED; - return "Please wait, another connection from this IP is still pending..."; - } - } - } - #else - if ( CompareIPs( tmpIP, level.clients[i].sess.IP ) ) - count++; - #endif - } - if ( count > g_maxConnPerIP.integer ) - { - // client->pers.connected = CON_DISCONNECTED; - return "Too many connections from the same IP"; - } - } - } - if ( ent->inuse ) {// if a player reconnects quickly after a disconnect, the client disconnect may never be called, thus flag can get lost in the ether G_LogPrintf( "Forcing disconnect on active client: %i\n", clientNum ); diff --git a/codemp/game/g_xcvar.h b/codemp/game/g_xcvar.h index df9ee8094a..b689f4258b 100644 --- a/codemp/game/g_xcvar.h +++ b/codemp/game/g_xcvar.h @@ -71,7 +71,6 @@ XCVAR_DEF( g_allowHighPingDuelist, "1", NULL, CVAR_NONE, qtrue XCVAR_DEF( g_allowNPC, "1", NULL, CVAR_CHEAT, qtrue ) XCVAR_DEF( g_allowTeamVote, "1", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_allowVote, "-1", NULL, CVAR_ARCHIVE, qfalse ) -XCVAR_DEF( g_antiFakePlayer, "1", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_armBreakage, "0", NULL, CVAR_NONE, qtrue ) XCVAR_DEF( g_austrian, "0", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_autoMapCycle, "0", NULL, CVAR_ARCHIVE|CVAR_NORESTART, qtrue ) @@ -115,7 +114,6 @@ XCVAR_DEF( g_locationBasedDamage, "1", NULL, CVAR_NONE, qtrue ) XCVAR_DEF( g_log, "games.log", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_logClientInfo, "0", NULL, CVAR_ARCHIVE, qtrue ) XCVAR_DEF( g_logSync, "0", NULL, CVAR_ARCHIVE, qfalse ) -XCVAR_DEF( g_maxConnPerIP, "3", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_maxForceRank, "7", NULL, CVAR_SERVERINFO|CVAR_ARCHIVE|CVAR_LATCH, qfalse ) XCVAR_DEF( g_maxGameClients, "0", NULL, CVAR_SERVERINFO|CVAR_LATCH|CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_maxHolocronCarry, "3", NULL, CVAR_LATCH, qfalse ) diff --git a/codemp/qcommon/q_shared.h b/codemp/qcommon/q_shared.h index 526ede7d25..dc646dbf87 100644 --- a/codemp/qcommon/q_shared.h +++ b/codemp/qcommon/q_shared.h @@ -1894,8 +1894,6 @@ enum { FONT_SMALL2 }; -void NET_AddrToString( char *out, size_t size, void *addr ); - qboolean Q_InBitflags( const uint32_t *bits, int index, uint32_t bitsPerByte ); void Q_AddToBitflags( uint32_t *bits, int index, uint32_t bitsPerByte ); void Q_RemoveFromBitflags( uint32_t *bits, int index, uint32_t bitsPerByte ); diff --git a/codemp/server/server.h b/codemp/server/server.h index 6a14f7d78d..0ebec63a0c 100644 --- a/codemp/server/server.h +++ b/codemp/server/server.h @@ -276,6 +276,8 @@ extern cvar_t *sv_banFile; extern cvar_t *sv_maxOOBRate; extern cvar_t *sv_maxOOBRateIP; extern cvar_t *sv_autoWhitelist; +extern cvar_t *sv_antiFakePlayer; +extern cvar_t *sv_maxConnPerIP; extern serverBan_t serverBans[SERVER_MAXBANS]; extern int serverBansCount; diff --git a/codemp/server/sv_client.cpp b/codemp/server/sv_client.cpp index 073fbbe6a4..e2e9db7bf5 100644 --- a/codemp/server/sv_client.cpp +++ b/codemp/server/sv_client.cpp @@ -24,6 +24,7 @@ along with this program; if not, see . // sv_client.c -- server code for dealing with clients +#include "qcommon/q_shared.h" #include "server.h" #include "qcommon/stringed_ingame.h" @@ -315,6 +316,23 @@ void SV_DirectConnect( netadr_t from ) { // save the userinfo Q_strncpyz( newcl->userinfo, userinfo, sizeof(newcl->userinfo) ); + if (sv_antiFakePlayer->integer) { + // check for > sv_maxConnPerIP connections from same IP + int count = 0, i = 0; + for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) { + if (NET_CompareBaseAdr(svs.clients[clientNum].netchan.remoteAddress, svs.clients[i].netchan.remoteAddress)) { + count++; + } + } + if (count > sv_maxConnPerIP->integer) { + cl->state = CS_FREE; + denied = "Too many connections from the same IP"; + NET_OutOfBandPrint(NS_SERVER, from, "print\n%s\n", denied); + Com_DPrintf("Game rejected a connection: %s.\n", denied); + return; + } + } + // get the game a chance to reject this connection or modify the userinfo denied = GVM_ClientConnect( clientNum, qtrue, qfalse ); // firstTime = qtrue if ( denied ) { diff --git a/codemp/server/sv_init.cpp b/codemp/server/sv_init.cpp index be62b91bf1..f7c277039c 100644 --- a/codemp/server/sv_init.cpp +++ b/codemp/server/sv_init.cpp @@ -1013,6 +1013,8 @@ void SV_Init (void) { sv_maxOOBRate = Cvar_Get("sv_maxOOBRate", "1000", CVAR_ARCHIVE, "Maximum rate of handling incoming server commands" ); sv_maxOOBRateIP = Cvar_Get("sv_maxOOBRateIP", "1", CVAR_ARCHIVE, "Maximum rate of handling incoming server commands per IP address" ); sv_autoWhitelist = Cvar_Get("sv_autoWhitelist", "1", CVAR_ARCHIVE, "Save player IPs to allow them using server during DOS attack" ); + sv_antiFakePlayer = Cvar_Get("sv_antiFakePlayer", "0", CVAR_ARCHIVE, "Additional fake player detection" ); + sv_maxConnPerIP = Cvar_Get("sv_maxConnPerIP", "3", CVAR_ARCHIVE, "Maximum amount of client connections for IP" ); // initialize bot cvars so they are listed and can be set before loading the botlib SV_BotInitCvars(); diff --git a/codemp/server/sv_main.cpp b/codemp/server/sv_main.cpp index 1bb2f7daf6..7b21e5e8ce 100644 --- a/codemp/server/sv_main.cpp +++ b/codemp/server/sv_main.cpp @@ -72,6 +72,8 @@ cvar_t *sv_banFile; cvar_t *sv_maxOOBRate; cvar_t *sv_maxOOBRateIP; cvar_t *sv_autoWhitelist; +cvar_t *sv_antiFakePlayer; +cvar_t *sv_maxConnPerIP; serverBan_t serverBans[SERVER_MAXBANS]; int serverBansCount = 0; From 69815e97d060707d83c5cf8886607a38fc31a764 Mon Sep 17 00:00:00 2001 From: Razish Date: Sun, 11 Feb 2024 04:17:42 +1100 Subject: [PATCH 2/3] fix connection status checks --- codemp/server/sv_client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codemp/server/sv_client.cpp b/codemp/server/sv_client.cpp index e2e9db7bf5..e78f53b2b7 100644 --- a/codemp/server/sv_client.cpp +++ b/codemp/server/sv_client.cpp @@ -320,11 +320,11 @@ void SV_DirectConnect( netadr_t from ) { // check for > sv_maxConnPerIP connections from same IP int count = 0, i = 0; for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) { - if (NET_CompareBaseAdr(svs.clients[clientNum].netchan.remoteAddress, svs.clients[i].netchan.remoteAddress)) { + if (cl->state >= CS_CONNECTED && NET_CompareBaseAdr(svs.clients[clientNum].netchan.remoteAddress, svs.clients[i].netchan.remoteAddress)) { count++; } } - if (count > sv_maxConnPerIP->integer) { + if (count >= sv_maxConnPerIP->integer) { cl->state = CS_FREE; denied = "Too many connections from the same IP"; NET_OutOfBandPrint(NS_SERVER, from, "print\n%s\n", denied); From bf4eb9ddb7c8580a009bd6db53cafc0de88544d3 Mon Sep 17 00:00:00 2001 From: Razish Date: Sun, 11 Feb 2024 15:45:32 +1100 Subject: [PATCH 3/3] backport antiFakePlayer to game module once again --- codemp/game/g_client.c | 25 ++++++++++++++++++++----- codemp/game/g_xcvar.h | 2 ++ codemp/server/sv_client.cpp | 2 +- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/codemp/game/g_client.c b/codemp/game/g_client.c index 2867f50d5e..e5cfce6805 100644 --- a/codemp/game/g_client.c +++ b/codemp/game/g_client.c @@ -2396,13 +2396,14 @@ restarts. ============ */ -static qboolean CompareIPs( const char *ip1, const char *ip2 ) -{ - while ( 1 ) { - if ( *ip1 != *ip2 ) +static qboolean CompareIPs(const char *ip1, const char *ip2) { + while (1) { + if (*ip1 != *ip2) { return qfalse; - if ( !*ip1 || *ip1 == ':' ) + } + if (!*ip1 || *ip1 == ':') { break; + } ip1++; ip2++; } @@ -2451,6 +2452,20 @@ char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot ) { } } + // check for >= g_maxConnPerIP connections from same IP + if (g_antiFakePlayer.integer && !isBot && firstTime) { + int count = 0, i = 0; + gclient_t *cl; + for (i = 0, cl = level.clients; i < sv_maxclients.integer; i++, cl++) { + if (cl->pers.connected >= CON_CONNECTING && CompareIPs(tmpIP, cl->sess.IP)) { + count++; + } + } + if (count >= g_maxConnPerIP.integer) { + return "Too many connections from the same IP"; + } + } + if ( ent->inuse ) {// if a player reconnects quickly after a disconnect, the client disconnect may never be called, thus flag can get lost in the ether G_LogPrintf( "Forcing disconnect on active client: %i\n", clientNum ); diff --git a/codemp/game/g_xcvar.h b/codemp/game/g_xcvar.h index b689f4258b..fad09b3633 100644 --- a/codemp/game/g_xcvar.h +++ b/codemp/game/g_xcvar.h @@ -71,6 +71,7 @@ XCVAR_DEF( g_allowHighPingDuelist, "1", NULL, CVAR_NONE, qtrue XCVAR_DEF( g_allowNPC, "1", NULL, CVAR_CHEAT, qtrue ) XCVAR_DEF( g_allowTeamVote, "1", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_allowVote, "-1", NULL, CVAR_ARCHIVE, qfalse ) +XCVAR_DEF( g_antiFakePlayer, "0", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_armBreakage, "0", NULL, CVAR_NONE, qtrue ) XCVAR_DEF( g_austrian, "0", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_autoMapCycle, "0", NULL, CVAR_ARCHIVE|CVAR_NORESTART, qtrue ) @@ -114,6 +115,7 @@ XCVAR_DEF( g_locationBasedDamage, "1", NULL, CVAR_NONE, qtrue ) XCVAR_DEF( g_log, "games.log", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_logClientInfo, "0", NULL, CVAR_ARCHIVE, qtrue ) XCVAR_DEF( g_logSync, "0", NULL, CVAR_ARCHIVE, qfalse ) +XCVAR_DEF( g_maxConnPerIP, "3", NULL, CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_maxForceRank, "7", NULL, CVAR_SERVERINFO|CVAR_ARCHIVE|CVAR_LATCH, qfalse ) XCVAR_DEF( g_maxGameClients, "0", NULL, CVAR_SERVERINFO|CVAR_LATCH|CVAR_ARCHIVE, qfalse ) XCVAR_DEF( g_maxHolocronCarry, "3", NULL, CVAR_LATCH, qfalse ) diff --git a/codemp/server/sv_client.cpp b/codemp/server/sv_client.cpp index e78f53b2b7..38e7e5323d 100644 --- a/codemp/server/sv_client.cpp +++ b/codemp/server/sv_client.cpp @@ -316,8 +316,8 @@ void SV_DirectConnect( netadr_t from ) { // save the userinfo Q_strncpyz( newcl->userinfo, userinfo, sizeof(newcl->userinfo) ); + // check for >= sv_maxConnPerIP connections from same IP if (sv_antiFakePlayer->integer) { - // check for > sv_maxConnPerIP connections from same IP int count = 0, i = 0; for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) { if (cl->state >= CS_CONNECTED && NET_CompareBaseAdr(svs.clients[clientNum].netchan.remoteAddress, svs.clients[i].netchan.remoteAddress)) {