Commit 0e437cf1 authored by Fabio Bas's avatar Fabio Bas
Browse files

Anti flood for game commands

parent 20603c7e
...@@ -60,8 +60,11 @@ public: ...@@ -60,8 +60,11 @@ public:
virtual int getMaxMessageCountPerInterval() const { return 0; } virtual int getMaxMessageCountPerInterval() const { return 0; }
virtual int getMaxMessageSizePerInterval() const { return 0; } virtual int getMaxMessageSizePerInterval() const { return 0; }
virtual int getMaxGamesPerUser() const { return 0; } virtual int getMaxGamesPerUser() const { return 0; }
virtual int getCommandCountingInterval() const { return 0; }
virtual int getMaxCommandCountPerInterval() const { return 0; }
virtual bool getThreaded() const { return false; } virtual bool getThreaded() const { return false; }
Server_DatabaseInterface *getDatabaseInterface() const; Server_DatabaseInterface *getDatabaseInterface() const;
int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; } int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; }
......
...@@ -217,12 +217,26 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const ...@@ -217,12 +217,26 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
if (!player) if (!player)
return Response::RespNotInRoom; return Response::RespNotInRoom;
int commandCountingInterval = server->getCommandCountingInterval();
int maxMessageCountPerInterval = server->getMaxMessageCountPerInterval();
GameEventStorage ges; GameEventStorage ges;
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.game_command_size() - 1; i >= 0; --i) { for (int i = cont.game_command_size() - 1; i >= 0; --i) {
const GameCommand &sc = cont.game_command(i); const GameCommand &sc = cont.game_command(i);
logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString())); logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));
if (commandCountingInterval > 0) {
int totalCount = 0;
if (commandCountOverTime.isEmpty())
commandCountOverTime.prepend(0);
++commandCountOverTime[0];
for (int i = 0; i < commandCountOverTime.size(); ++i)
totalCount += commandCountOverTime[i];
if (totalCount > maxMessageCountPerInterval)
return Response::RespChatFlood;
}
Response::ResponseCode resp = player->processGameCommand(sc, rc, ges); Response::ResponseCode resp = player->processGameCommand(sc, rc, ges);
if (resp != Response::RespOk) if (resp != Response::RespOk)
...@@ -314,7 +328,14 @@ void Server_ProtocolHandler::pingClockTimeout() ...@@ -314,7 +328,14 @@ void Server_ProtocolHandler::pingClockTimeout()
if (messageCountOverTime.size() > server->getMessageCountingInterval()) if (messageCountOverTime.size() > server->getMessageCountingInterval())
messageCountOverTime.removeLast(); messageCountOverTime.removeLast();
} }
interval = server->getCommandCountingInterval();
if (interval > 0) {
commandCountOverTime.prepend(0);
if (commandCountOverTime.size() > server->getCommandCountingInterval())
commandCountOverTime.removeLast();
}
if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime()) if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime())
prepareDestroy(); prepareDestroy();
++timeRunning; ++timeRunning;
......
...@@ -51,7 +51,7 @@ protected: ...@@ -51,7 +51,7 @@ protected:
bool acceptsRoomListChanges; bool acceptsRoomListChanges;
virtual void logDebugMessage(const QString & /* message */) { } virtual void logDebugMessage(const QString & /* message */) { }
private: private:
QList<int> messageSizeOverTime, messageCountOverTime; QList<int> messageSizeOverTime, messageCountOverTime, commandCountOverTime;
int timeRunning, lastDataReceived; int timeRunning, lastDataReceived;
QTimer *pingClock; QTimer *pingClock;
......
...@@ -130,7 +130,7 @@ max_users_per_address=4 ...@@ -130,7 +130,7 @@ max_users_per_address=4
; IP addresses listed (ignoring the max_users_per_address). Default is "127.0.0.1,::1"; example: "192.73.233.244,81.4.100.74" ; IP addresses listed (ignoring the max_users_per_address). Default is "127.0.0.1,::1"; example: "192.73.233.244,81.4.100.74"
trusted_sources="127.0.0.1,::1" trusted_sources="127.0.0.1,::1"
; Servatrice can avoid users from flooding rooms with large number messages in an interval of time. ; Servatrice can avoid users from flooding rooms with large number of messages in an interval of time.
; This setting defines the length in seconds of the considered interval; default is 10 ; This setting defines the length in seconds of the considered interval; default is 10
message_counting_interval=10 message_counting_interval=10
...@@ -143,6 +143,12 @@ max_message_count_per_interval=10 ...@@ -143,6 +143,12 @@ max_message_count_per_interval=10
; Maximum number of games a single user can create; default is 5 ; Maximum number of games a single user can create; default is 5
max_games_per_user=5 max_games_per_user=5
; Servatrice can avoid users from flooding games with large number of game commands in an interval of time.
; This setting defines the length in seconds of the considered interval; default is 10
command_counting_interval=10
; Maximum number of game commands in an interval before new commands gets dropped; default is 10
max_command_count_per_interval=10
[logging] [logging]
......
...@@ -259,6 +259,8 @@ bool Servatrice::initServer() ...@@ -259,6 +259,8 @@ bool Servatrice::initServer()
maxMessageCountPerInterval = settingsCache->value("security/max_message_count_per_interval", 10).toInt(); maxMessageCountPerInterval = settingsCache->value("security/max_message_count_per_interval", 10).toInt();
maxMessageSizePerInterval = settingsCache->value("security/max_message_size_per_interval", 1000).toInt(); maxMessageSizePerInterval = settingsCache->value("security/max_message_size_per_interval", 1000).toInt();
maxGamesPerUser = settingsCache->value("security/max_games_per_user", 5).toInt(); maxGamesPerUser = settingsCache->value("security/max_games_per_user", 5).toInt();
commandCountingInterval = settingsCache->value("game/command_counting_interval", 10).toInt();
maxCommandCountPerInterval = settingsCache->value("game/max_command_count_per_interval", 10).toInt();
try { if (settingsCache->value("servernetwork/active", 0).toInt()) { try { if (settingsCache->value("servernetwork/active", 0).toInt()) {
qDebug() << "Connecting to ISL network."; qDebug() << "Connecting to ISL network.";
......
...@@ -115,8 +115,8 @@ private: ...@@ -115,8 +115,8 @@ private:
QMutex txBytesMutex, rxBytesMutex; QMutex txBytesMutex, rxBytesMutex;
quint64 txBytes, rxBytes; quint64 txBytes, rxBytes;
int maxGameInactivityTime, maxPlayerInactivityTime; int maxGameInactivityTime, maxPlayerInactivityTime;
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser, commandCountingInterval, maxCommandCountPerInterval;
QString shutdownReason; QString shutdownReason;
int shutdownMinutes; int shutdownMinutes;
QTimer *shutdownTimer; QTimer *shutdownTimer;
...@@ -143,6 +143,8 @@ public: ...@@ -143,6 +143,8 @@ public:
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; } int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; } int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
int getMaxGamesPerUser() const { return maxGamesPerUser; } int getMaxGamesPerUser() const { return maxGamesPerUser; }
int getCommandCountingInterval() const { return commandCountingInterval; }
int getMaxCommandCountPerInterval() const { return maxCommandCountPerInterval; }
AuthenticationMethod getAuthenticationMethod() const { return authenticationMethod; } AuthenticationMethod getAuthenticationMethod() const { return authenticationMethod; }
QString getDbPrefix() const { return dbPrefix; } QString getDbPrefix() const { return dbPrefix; }
int getServerId() const { return serverId; } int getServerId() const { return serverId; }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment