diff --git a/bin/config_sample/config.ini b/bin/config_sample/config.ini index 34e14e4..bd43618 100644 --- a/bin/config_sample/config.ini +++ b/bin/config_sample/config.ini @@ -17,6 +17,7 @@ modpass=changeme logbuffer=500 logging=modcall maximum_statements=10 +multiclient_limit=15 [Dice] max_value=100 diff --git a/include/server.h b/include/server.h index 0d44b0e..f96fd79 100644 --- a/include/server.h +++ b/include/server.h @@ -281,6 +281,11 @@ class Server : public QObject { */ QStringList gimp_list; + /** + * @brief Integer representing the maximum number of clients allowed to connect from the same IP + */ + int multiclient_limit; + public slots: /** * @brief Handles a new connection. diff --git a/src/packets.cpp b/src/packets.cpp index 39709b1..98e25af 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -301,6 +301,17 @@ void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPack #endif remote_ip = QHostAddress(argv[0]); calculateIpid(); + + int multiclient_count = 0; + for (AOClient* joined_client : server->clients) { + if (remote_ip.isEqual(joined_client->remote_ip)) + multiclient_count++; + } + + if (multiclient_count > server->multiclient_limit) { + socket->close(); + return; + } } } diff --git a/src/server.cpp b/src/server.cpp index e0c5825..30dea51 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -114,14 +114,29 @@ void Server::clientConnected() break; } AOClient* client = new AOClient(this, socket, this, user_id); - if (db_manager->isIPBanned(socket->peerAddress())) { + + int multiclient_count = 1; + bool is_at_multiclient_limit = false; + bool is_banned = db_manager->isIPBanned(socket->peerAddress()); + for (AOClient* joined_client : clients) { + if (client->remote_ip.isEqual(joined_client->remote_ip)) + multiclient_count++; + } + + if (multiclient_count > multiclient_limit && !client->remote_ip.isLoopback()) // TODO: make this configurable + is_at_multiclient_limit = true; + + if (is_banned) { AOPacket ban_reason("BD", {db_manager->getBanReason(socket->peerAddress())}); socket->write(ban_reason.toUtf8()); + } + if (is_banned || is_at_multiclient_limit) { socket->flush(); client->deleteLater(); socket->close(); return; } + clients.append(client); connect(socket, &QTcpSocket::disconnected, client, &AOClient::clientDisconnected); @@ -264,6 +279,10 @@ void Server::loadServerConfig() afk_timeout = config.value("afk_timeout", "300").toInt(&afk_timeout_conversion_success); if (!afk_timeout_conversion_success) afk_timeout = 300; + bool multiclient_limit_conversion_success; + multiclient_limit = config.value("multiclient_limit", "15").toInt(&multiclient_limit_conversion_success); + if (!multiclient_limit_conversion_success) + multiclient_limit = 15; config.endGroup(); //Load dice values