mirror of
https://git.code.sf.net/p/quake/newtree
synced 2024-11-25 21:41:57 +00:00
Basic DoS flood attack protections. Use sv_netdosprotect 1 to turn them on.
(quite experimental, these might break something...) Cvars added: sv_allow_log, sv_allow_status, sv_allow_ping, sv_netdosprotect Commands added: netdosexpire, netdosvalues
This commit is contained in:
parent
0bbc70dbd6
commit
afc467b84f
2 changed files with 133 additions and 9 deletions
|
@ -273,6 +273,23 @@ typedef struct
|
|||
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
|
||||
} server_static_t;
|
||||
|
||||
//=============================================================================
|
||||
// DoSflood protection
|
||||
//=============================================================================
|
||||
typedef struct
|
||||
{
|
||||
netadr_t adr;
|
||||
double issued;
|
||||
int floodcount;
|
||||
int cmdcount;
|
||||
double firstseen;
|
||||
} flood_t;
|
||||
|
||||
enum {FLOOD_PING, FLOOD_LOG, FLOOD_CONNECT, FLOOD_STATUS, FLOOD_RCON, FLOOD_BAN};
|
||||
|
||||
#define DOSFLOODCMDS 6
|
||||
#define DOSFLOODIP 64 // remember latest 64 IP's for each cmd.
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// edict->movetype values
|
||||
|
|
107
source/sv_main.c
107
source/sv_main.c
|
@ -62,6 +62,19 @@ netadr_t master_adr[MAX_MASTERS]; // address of group servers
|
|||
|
||||
client_t *host_client; // current client
|
||||
|
||||
// DoS protection
|
||||
// FLOOD_PING, FLOOD_LOG, FLOOD_CONNECT, FLOOD_STATUS, FLOOD_RCON, FLOOD_BAN
|
||||
// fixme: these default values need to be tweaked after more testing
|
||||
|
||||
double netdosexpire[DOSFLOODCMDS] = {1,1,2,0.9,1,5};
|
||||
double netdosvalues[DOSFLOODCMDS] = {12,1,3,2,1,1};
|
||||
|
||||
cvar_t *sv_netdosprotect; // tone down DoS from quake servers
|
||||
|
||||
cvar_t *sv_allow_status;
|
||||
cvar_t *sv_allow_log;
|
||||
cvar_t *sv_allow_ping;
|
||||
|
||||
cvar_t *fs_globalcfg;
|
||||
|
||||
cvar_t *sv_mintic; // bound the size of the
|
||||
|
@ -368,6 +381,79 @@ CONNECTIONLESS COMMANDS
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================
|
||||
CheckForFlood :: EXPERIMENTAL
|
||||
|
||||
Makes it more difficult to use Quake servers for DoS attacks against other sites.
|
||||
|
||||
Bad sides: affects gamespy and spytools somewhat...
|
||||
|
||||
================
|
||||
*/
|
||||
|
||||
int CheckForFlood(char cmdtype)
|
||||
{
|
||||
static qboolean firsttime=true;
|
||||
static flood_t floodstatus[DOSFLOODCMDS][DOSFLOODIP];
|
||||
|
||||
int i;
|
||||
double currenttime;
|
||||
double oldestTime;
|
||||
static double lastmessagetime=0;
|
||||
int oldest;
|
||||
|
||||
if (!sv_netdosprotect->value) return 0;
|
||||
|
||||
oldestTime=0x7fffffff;
|
||||
oldest=0;
|
||||
|
||||
if (firsttime) {
|
||||
memset(floodstatus,sizeof(flood_t)*DOSFLOODCMDS*DOSFLOODIP,0);
|
||||
firsttime=false;
|
||||
}
|
||||
|
||||
currenttime=Sys_DoubleTime();
|
||||
|
||||
for (i = 0 ; i < DOSFLOODIP ; i++)
|
||||
{
|
||||
if (NET_CompareBaseAdr (net_from, floodstatus[cmdtype][i].adr))
|
||||
break;
|
||||
if (floodstatus[cmdtype][i].issued < oldestTime)
|
||||
{
|
||||
oldestTime = floodstatus[cmdtype][i].issued;
|
||||
oldest = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i<DOSFLOODIP && floodstatus[cmdtype][i].issued)
|
||||
if(floodstatus[cmdtype][i].issued+netdosexpire[cmdtype]>currenttime)
|
||||
{
|
||||
floodstatus[cmdtype][i].floodcount+=1;
|
||||
if (floodstatus[cmdtype][i].floodcount>netdosvalues[cmdtype])
|
||||
{
|
||||
if (lastmessagetime+5<currenttime)
|
||||
Con_Printf("Blocking type %d flood from (or to) %s\n",cmdtype,NET_AdrToString(net_from));
|
||||
Con_Printf("%f %f\n",currenttime,floodstatus[cmdtype][i].issued);
|
||||
floodstatus[cmdtype][i].floodcount=0;
|
||||
floodstatus[cmdtype][i].issued = currenttime;
|
||||
floodstatus[cmdtype][i].cmdcount+=1;
|
||||
lastmessagetime=currenttime;
|
||||
return 1;
|
||||
}
|
||||
} else floodstatus[cmdtype][i].floodcount=0;
|
||||
|
||||
if (i == DOSFLOODIP)
|
||||
{
|
||||
i = oldest;
|
||||
floodstatus[cmdtype][i].adr = net_from;
|
||||
floodstatus[cmdtype][i].firstseen=currenttime;
|
||||
}
|
||||
floodstatus[cmdtype][i].issued = currenttime;
|
||||
floodstatus[cmdtype][i].cmdcount+=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SVC_Status
|
||||
|
@ -383,6 +469,10 @@ void SVC_Status (void)
|
|||
int ping;
|
||||
int top, bottom;
|
||||
|
||||
if (CheckForFlood(FLOOD_STATUS)) return;
|
||||
|
||||
if (!sv_allow_status->value) return;
|
||||
|
||||
Cmd_TokenizeString ("status");
|
||||
SV_BeginRedirect (RD_PACKET);
|
||||
Con_Printf ("%s\n", svs.info);
|
||||
|
@ -448,6 +538,9 @@ void SVC_Log (void)
|
|||
int seq;
|
||||
char data[MAX_DATAGRAM+64];
|
||||
|
||||
if (sv_allow_log->value) return;
|
||||
if (CheckForFlood(FLOOD_LOG)) return;
|
||||
|
||||
if (Cmd_Argc() == 2)
|
||||
seq = atoi(Cmd_Argv(1));
|
||||
else
|
||||
|
@ -482,6 +575,9 @@ void SVC_Ping (void)
|
|||
{
|
||||
char data;
|
||||
|
||||
if (!sv_allow_ping->value) return;
|
||||
if (CheckForFlood(FLOOD_PING)) return;
|
||||
|
||||
data = A2A_ACK;
|
||||
|
||||
NET_SendPacket (1, &data, net_from);
|
||||
|
@ -504,6 +600,7 @@ void SVC_GetChallenge (void)
|
|||
int oldest;
|
||||
int oldestTime;
|
||||
|
||||
// if (CheckForFlood(FLOOD_CHALLENGE)) return;
|
||||
oldest = 0;
|
||||
oldestTime = 0x7fffffff;
|
||||
|
||||
|
@ -557,6 +654,8 @@ void SVC_DirectConnect (void)
|
|||
int version;
|
||||
int challenge;
|
||||
|
||||
if (CheckForFlood(FLOOD_CONNECT)) return;
|
||||
|
||||
version = atoi(Cmd_Argv(1));
|
||||
if (version != PROTOCOL_VERSION)
|
||||
{
|
||||
|
@ -781,6 +880,7 @@ void SVC_RemoteCommand (void)
|
|||
int i;
|
||||
char remaining[1024];
|
||||
|
||||
if (CheckForFlood(FLOOD_RCON)) return;
|
||||
|
||||
if (!Rcon_Validate ()) {
|
||||
Con_Printf ("Bad rcon from %s:\n%s\n"
|
||||
|
@ -1076,6 +1176,8 @@ void SV_SendBan (void)
|
|||
{
|
||||
char data[128];
|
||||
|
||||
if (CheckForFlood(FLOOD_BAN)) return;
|
||||
|
||||
data[0] = data[1] = data[2] = data[3] = 0xff;
|
||||
data[4] = A2C_PRINT;
|
||||
data[5] = 0;
|
||||
|
@ -1393,6 +1495,11 @@ void SV_InitLocal (void)
|
|||
sv_timekick_fuzz = Cvar_Get("sv_timekick_fuzz", "15", CVAR_NONE, "Time cheat \"fuzz factor\"");
|
||||
sv_timekick_interval = Cvar_Get("sv_timekick_interval", "30", CVAR_NONE, "Time cheat check interval");
|
||||
|
||||
sv_allow_log = Cvar_Get("sv_allow_log", "1", CVAR_NONE, "Allow remote logging");
|
||||
sv_allow_status = Cvar_Get("sv_allow_status","1", CVAR_NONE, "Allow remote status queries (gamespy etc)");
|
||||
sv_allow_ping = Cvar_Get("sv_allow_pings","1", CVAR_NONE, "Allow remote pings (gamespy etc)");
|
||||
sv_netdosprotect = Cvar_Get("sv_netdosprotect","0", CVAR_NONE, "DoS flood attack protection");
|
||||
|
||||
sv_timestamps = Cvar_Get ("sv_timestamps", "0", CVAR_NONE, "Time/date stamps in log entries");
|
||||
sv_timefmt = Cvar_Get ("sv_timefmt", "[%b %e %X] ", CVAR_NONE, "Time/date format to use");
|
||||
|
||||
|
|
Loading…
Reference in a new issue