diff --git a/codemp/game/g_client.c b/codemp/game/g_client.c index a46845ddb5..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,36 +2452,18 @@ 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"; + // 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 ) diff --git a/codemp/game/g_xcvar.h b/codemp/game/g_xcvar.h index df9ee8094a..fad09b3633 100644 --- a/codemp/game/g_xcvar.h +++ b/codemp/game/g_xcvar.h @@ -71,7 +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, "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 ) 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..38e7e5323d 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) ); + // check for >= sv_maxConnPerIP connections from same IP + if (sv_antiFakePlayer->integer) { + 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)) { + 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;