Skip to content

Commit

Permalink
Add netlimit and connlimit
Browse files Browse the repository at this point in the history
  • Loading branch information
fokkonaut committed Jan 7, 2020
1 parent 637ee14 commit 26b2437
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 7 deletions.
25 changes: 25 additions & 0 deletions src/engine/server/server.cpp
Expand Up @@ -434,6 +434,8 @@ int CServer::Init()
m_aClients[i].m_aClan[0] = 0;
m_aClients[i].m_Country = -1;
m_aClients[i].m_Snapshots.Init();
m_aClients[i].m_Traffic = 0;
m_aClients[i].m_TrafficSince = 0;
}

m_CurrentGameTick = 0;
Expand Down Expand Up @@ -749,6 +751,8 @@ int CServer::NewClientCallback(int ClientID, void *pUser)
pThis->m_aClients[ClientID].m_pMapListEntryToSend = 0;
pThis->m_aClients[ClientID].m_NoRconNote = false;
pThis->m_aClients[ClientID].m_Quitting = false;
pThis->m_aClients[ClientID].m_Traffic = 0;
pThis->m_aClients[ClientID].m_TrafficSince = 0;
pThis->m_aClients[ClientID].Reset();
pThis->GameServer()->OnClientEngineJoin(ClientID);
return 0;
Expand Down Expand Up @@ -781,6 +785,8 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
pThis->m_aClients[ClientID].m_pMapListEntryToSend = 0;
pThis->m_aClients[ClientID].m_NoRconNote = false;
pThis->m_aClients[ClientID].m_Quitting = false;
pThis->m_aClients[ClientID].m_Traffic = 0;
pThis->m_aClients[ClientID].m_TrafficSince = 0;
pThis->m_aClients[ClientID].m_Snapshots.PurgeAll();

pThis->GameServer()->OnClientEngineDrop(ClientID, pReason);
Expand Down Expand Up @@ -923,6 +929,25 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
SendMsg(&Packer, MSGFLAG_VITAL, ClientID);
}

if(g_Config.m_SvNetlimit && Msg != NETMSG_REQUEST_MAP_DATA)
{
int64 Now = time_get();
int64 Diff = Now - m_aClients[ClientID].m_TrafficSince;
float Alpha = g_Config.m_SvNetlimitAlpha / 100.0f;
float Limit = (float)g_Config.m_SvNetlimit * 1024 / time_freq();

if (m_aClients[ClientID].m_Traffic > Limit)
{
m_NetServer.NetBan()->BanAddr(&pPacket->m_Address, 600, "Stressing network");
return;
}
if (Diff > 100)
{
m_aClients[ClientID].m_Traffic = (Alpha * ((float)pPacket->m_DataSize / Diff)) + (1.0f - Alpha) * m_aClients[ClientID].m_Traffic;
m_aClients[ClientID].m_TrafficSince = Now;
}
}

if(Sys)
{
// system message
Expand Down
3 changes: 3 additions & 0 deletions src/engine/server/server.h
Expand Up @@ -143,6 +143,9 @@ class CServer : public IServer
int m_Authed;
int m_AuthTries;

float m_Traffic;
int64 m_TrafficSince;

int m_MapChunk;
bool m_NoRconNote;
bool m_Quitting;
Expand Down
8 changes: 8 additions & 0 deletions src/engine/shared/config_variables.h
Expand Up @@ -176,4 +176,12 @@ MACRO_CONFIG_INT(SvChatPenalty, sv_chat_penalty, 250, 50, 1000, CFGFLAG_SERVER,
MACRO_CONFIG_INT(SvChatThreshold, sv_chat_threshold, 1000, 50, 10000, CFGFLAG_SERVER, "if chats core exceeds this, the player will be muted for sv_spam_mute_duration seconds")
MACRO_CONFIG_INT(SvSpamMuteDuration, sv_spam_mute_duration, 60, 0, 3600, CFGFLAG_SERVER, "how many seconds to mute, if player triggers mute on spam. 0 = off")
MACRO_CONFIG_INT(SvShutdownWhenEmpty, sv_shutdown_when_empty, 0, 0, 1, CFGFLAG_SERVER, "Shutdown server as soon as no one is on it anymore")

// netlimit
MACRO_CONFIG_INT(SvNetlimit, sv_netlimit, 0, 0, 10000, CFGFLAG_SERVER, "Netlimit: Maximum amount of traffic a client is allowed to use (in kb/s)")
MACRO_CONFIG_INT(SvNetlimitAlpha, sv_netlimit_alpha, 50, 1, 100, CFGFLAG_SERVER, "Netlimit: Alpha of Exponention moving average")

// conn limit
MACRO_CONFIG_INT(SvConnlimit, sv_connlimit, 4, 0, 100, CFGFLAG_SERVER, "Connlimit: Number of connections an IP is allowed to do in a timespan")
MACRO_CONFIG_INT(SvConnlimitTime, sv_connlimit_time, 20, 0, 1000, CFGFLAG_SERVER, "Connlimit: Time in which IP's connections are counted")
#endif
14 changes: 14 additions & 0 deletions src/engine/shared/network.h
Expand Up @@ -131,6 +131,9 @@ enum

NET_CONN_BUFFERSIZE=1024*32,

// DDRace
NET_CONNLIMIT_IPS=16,

NET_ENUM_TERMINATOR
};

Expand Down Expand Up @@ -419,6 +422,15 @@ class CNetServer
NETFUNC_DELCLIENT m_pfnDelClient;
void *m_UserPtr;

struct CSpamConn
{
NETADDR m_Addr;
int64 m_Time;
int m_Conns;
};

CSpamConn m_aSpamConns[NET_CONNLIMIT_IPS];

CNetRecvUnpacker m_RecvUnpacker;

CNetTokenManager m_TokenManager;
Expand Down Expand Up @@ -450,6 +462,8 @@ class CNetServer

//
void SetMaxClientsPerIP(int Max);

bool Connlimit(NETADDR Addr);
};

class CNetConsole
Expand Down
49 changes: 42 additions & 7 deletions src/engine/shared/network_server.cpp
Expand Up @@ -6,6 +6,7 @@

#include "netban.h"
#include "network.h"
#include "config.h"


bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags)
Expand Down Expand Up @@ -80,13 +81,7 @@ int CNetServer::Update()
m_aSlots[i].m_Connection.Update();
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR)
{
if(Now - m_aSlots[i].m_Connection.ConnectTime() < time_freq() && NetBan())
{
if(NetBan()->BanAddr(ClientAddr(i), 60, "Stressing network") == -1)
Drop(i, m_aSlots[i].m_Connection.ErrorString());
}
else
Drop(i, m_aSlots[i].m_Connection.ErrorString());
Drop(i, m_aSlots[i].m_Connection.ErrorString());
}
}

Expand Down Expand Up @@ -172,6 +167,13 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken)
{
if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT)
{
if (Connlimit(Addr))
{
const char LimitMsg[] = "Too many connections in a short time";
CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, LimitMsg, str_length(LimitMsg) + 1);
return 0; // failed to add client
}

bool Found = false;

// only allow a specific number of players with the same ip
Expand Down Expand Up @@ -311,3 +313,36 @@ void CNetServer::SetMaxClientsPerIP(int Max)

m_MaxClientsPerIP = Max;
}

bool CNetServer::Connlimit(NETADDR Addr)
{
int64 Now = time_get();
int Oldest = 0;

for(int i = 0; i < NET_CONNLIMIT_IPS; ++i)
{
if(!net_addr_comp(&m_aSpamConns[i].m_Addr, &Addr))
{
if(m_aSpamConns[i].m_Time > Now - time_freq() * g_Config.m_SvConnlimitTime)
{
if(m_aSpamConns[i].m_Conns >= g_Config.m_SvConnlimit)
return true;
}
else
{
m_aSpamConns[i].m_Time = Now;
m_aSpamConns[i].m_Conns = 0;
}
m_aSpamConns[i].m_Conns++;
return false;
}

if(m_aSpamConns[i].m_Time < m_aSpamConns[Oldest].m_Time)
Oldest = i;
}

m_aSpamConns[Oldest].m_Addr = Addr;
m_aSpamConns[Oldest].m_Time = Now;
m_aSpamConns[Oldest].m_Conns = 1;
return false;
}

0 comments on commit 26b2437

Please sign in to comment.