Skip to content

Commit

Permalink
update rate limit to not ban, but instead "lock clients out" for a pe…
Browse files Browse the repository at this point in the history
…riod of time, around a minute. upped rate limit to require 6 tokens, from 5. added stac_print_to_admin_console as well
  • Loading branch information
sapphonie committed Jan 20, 2024
1 parent 13241d1 commit f440909
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 84 deletions.
2 changes: 1 addition & 1 deletion scripting/stac.sp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
#pragma semicolon 1
#pragma newdecls required

#define PLUGIN_VERSION "6.1.3-beta8"
#define PLUGIN_VERSION "6.1.3-beta10"

#define UPDATE_URL "https://raw.githubusercontent.com/sapphonie/StAC-tf2/master/updatefile.txt"

Expand Down
101 changes: 22 additions & 79 deletions scripting/stac/stac_client.sp
Original file line number Diff line number Diff line change
Expand Up @@ -44,95 +44,38 @@ public bool OnClientPreConnectEx(const char[] name, char password[255], const ch
strcopy(latestIP, sizeof(latestIP), ip);
strcopy(latestSteamID, sizeof(latestSteamID), steamID);


if (!stac_prevent_connect_spam.BoolValue)
{
return true;
}

// TODO: does this need to be higher? or lower? or...?
static int threshold = 5;
// connects == how many times have they connected recently, it decays by 1 every 5 seconds
// threshold == how many times is "too many" - TODO: does this need to be higher? or lower? or...?
int connects;
static int threshold = 6;

IPBuckets.GetValue(ip, connects); // 0 if not present
connects++;

if (connects >= threshold)
{
rejectReason = "Rate limited.";

DataPack steamidPlusIP = new DataPack();
steamidPlusIP.Reset(true);
steamidPlusIP.WriteString(steamID);
steamidPlusIP.WriteString(ip);
steamidPlusIP.WriteString(name);
steamidPlusIP.Reset(false);

// This is not arbitrary!
RequestFrame(DelayedRateLimitBan, steamidPlusIP);

rejectReason = "Rate limited. Please try again in a bit.";
if (connects < threshold + 5)
{
connects += 5; // Lock them out for a bit if they really will not stop spamming after getting rate limited
}
return false;
}
IPBuckets.SetValue(ip, connects);

if (stac_debug.BoolValue)
{
StacLog("-> connects from ip %s %i", ip, connects);
}
//if (stac_debug.BoolValue)
//{
StacLog("[stac_prevent_connect_spam - OnClientPreConnectEx] %i connects from ip %s", connects, ip);
//}

return true;
}

void DelayedRateLimitBan(DataPack dp)
{
dp.Reset(false);
char steamID[MAX_AUTHID_LENGTH];
char ipAddr[256];
char playerName[MAX_NAME_LENGTH];
dp.ReadString(steamID, sizeof(steamID));
dp.ReadString(ipAddr, sizeof(ipAddr));
dp.ReadString(playerName, sizeof(playerName));
dp.Reset(true);
delete dp;

static int rateLimitBanTime = 5;

// BanIdentity(steamID, 60, BANFLAG_AUTHID, "");
// BanIdentity(ip, 60, BANFLAG_IP, "");

// THE REASON we are doing this so weirdly, is so that we hook into srcds's built in
// "firewall", basically, where with the default game banning system,
// srcds will ignore packets from banned ips.
// this prevents any clients from spamming, in a way that would otherwise not really be possible,
// without stupid memory hacks that would be overcomplicated anyway since this already exists

// We're doing sm_addban / sm_banip because SourceBans, at least, will propagate this to other servers as well
// which is what we want, so people don't have to get individually banned on each server on the same network that they try to spam on

// Probably before un-betaing this, i'm going to try to move this to sm_ban and then addip after?
// I don't really know. it's a tricky race condition here, since we're after OnClientPreConnectEx callback, so they should be rejected,
// but they can rejoin, but regardless we don't actually have a client index yet?
#if 0
if ( CommandExists("sm_banip") && CommandExists("sm_addban") )
{
ServerCommand("sm_addban %i %s %s", rateLimitBanTime, steamID, "Rate limited");
ServerCommand("sm_banip %s %i %s", ipAddr, rateLimitBanTime, "Rate limited");
}
else
{
#endif

ServerCommand("addip %i %s", rateLimitBanTime, ipAddr);
ServerCommand("banid %i %s kick", rateLimitBanTime, steamID);
#if 0
}
#endif
char formattedMsg[1024];
Format(formattedMsg, sizeof(formattedMsg), "Rate limited %s / %s / %s for %i minutes for connect spam", playerName, steamID, ipAddr, rateLimitBanTime);

StacLog(formattedMsg);

StacNotify(0, formattedMsg, 1);
}

Action LeakIPConnectBucket(Handle timer)
{
if (!stac_prevent_connect_spam.BoolValue)
Expand All @@ -152,17 +95,17 @@ Action LeakIPConnectBucket(Handle timer)
IPBuckets.GetValue(ip, connects); // 0 if not present per zero-init above
connects--;

if (stac_debug.BoolValue)
{
StacLog("(LeakIPConnectBucket) connects from ip %s %i", ip, connects);
}
//if (stac_debug.BoolValue)
//{
StacLog("[stac_prevent_connect_spam - LeakIPConnectBucket] %i connects from ip %s", connects, ip);
//}

if (connects <= 0)
{
if (stac_debug.BoolValue)
{
StacLog("-> connects from ip %s %i [ REMOVING ] ", ip, connects);
}
//if (stac_debug.BoolValue)
//{
StacLog("[stac_prevent_connect_spam - LeakIPConnectBucket] %i connects from ip %s [ REMOVING ] ", connects, ip);
//}

IPBuckets.Remove(ip);
continue;
Expand Down
17 changes: 16 additions & 1 deletion scripting/stac/stac_cvars.sp
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@ void initCvars()
(
"stac_prevent_connect_spam",
"1",
"[StAC] (BETA DETECTION) use a \"leaky bucket\" algorithm to prevent the same clients from spamming connect requests to your server. temp bans clients for 60 minutes if they hit the limit.\n\
"[StAC] (BETA DETECTION) use a \"leaky bucket\" algorithm to prevent the same clients from spamming connect requests to your server.\n\
locks out clients for a bit (a minute or so) after they hit the limit.\n\
(recommended 1)",
FCVAR_NONE,
true,
Expand All @@ -379,6 +380,20 @@ void initCvars()
1.0
);

//
stac_print_to_admin_console =
AutoExecConfig_CreateConVar
(
"stac_print_to_admin_console",
"1",
"[StAC] print StAC logging messages to the client console of all online admins.\n\
(recommended 1)",
FCVAR_NONE,
true,
0.0,
true,
1.0
);

initUsercmdCvars();
// actually exec the cfg after initing cvars lol
Expand Down
1 change: 1 addition & 0 deletions scripting/stac/stac_globals.sp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ ConVar stac_silent;
ConVar stac_max_connections_from_ip;
ConVar stac_work_with_sv_cheats;
ConVar stac_prevent_connect_spam;
ConVar stac_print_to_admin_console;

/***** Server based stuff *****/

Expand Down
8 changes: 5 additions & 3 deletions scripting/stac/stac_stocks.sp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ void StacLog(const char[] format, any ...)
// }

PrintToServer("%s", colored_buffer);
#if 0
PrintToConsoleAllAdmins("%s", buffer);
#endif

if (stac_print_to_admin_console.GetBool())
{
PrintToConsoleAllAdmins("%s", buffer);
}
}

void StacLogDemo()
Expand Down

0 comments on commit f440909

Please sign in to comment.