mirror of
https://bitbucket.org/seefoe/src.git
synced 2026-07-30 00:15:46 -04:00
this probably has at least one mistake/bug/typo but will move our DoS
protection into the low level UDP lib
This commit is contained in:
@@ -142,6 +142,7 @@ LoginServer::LoginServer() :
|
||||
NetworkSetupData setup;
|
||||
setup.port = ConfigLoginServer::getClientServicePort();
|
||||
setup.maxConnections = ConfigLoginServer::getMaxClients();
|
||||
setup.maxConnectionsPerIP = ConfigLoginServer::getMaxConnectionsPerIP();
|
||||
setup.keepAliveDelay = 45000;
|
||||
setup.compress = ConfigLoginServer::getCompressClientNetworkTraffic();
|
||||
setup.useTcp = false;
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace ConfigSharedNetworkNamespace
|
||||
int outgoingBufferSize;
|
||||
int clockSyncDelay;
|
||||
int maxConnections;
|
||||
int maxConnectionsPerIP;
|
||||
int maxRawPacketSize;
|
||||
int maxInstandingPackets;
|
||||
int maxOutstandingBytes;
|
||||
@@ -506,6 +507,11 @@ bool ConfigSharedNetwork::getLogSendingTooMuchData()
|
||||
return logSendingTooMuchData;
|
||||
}
|
||||
|
||||
int ConfigSharedNetwork::getMaxConnectionsPerIP()
|
||||
{
|
||||
return maxConnectionsPerIP;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void ConfigSharedNetwork::install(int newClockSyncDelay)
|
||||
@@ -518,6 +524,7 @@ void ConfigSharedNetwork::install(int newClockSyncDelay)
|
||||
KEY_INT (incomingBufferSize, 4 * 1024 * 1024);
|
||||
KEY_INT (outgoingBufferSize, 4 * 1024 * 1024);
|
||||
KEY_INT (maxConnections, 1000);
|
||||
KEY_INT (maxConnectionsPerIP, 0); // unlimited
|
||||
KEY_INT (maxRawPacketSize, 496);
|
||||
KEY_INT (maxInstandingPackets, 400);
|
||||
KEY_INT (maxOutstandingBytes, 200 * 1024);
|
||||
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
static int getNetworkHandlerDispatchThrottleTimeMilliseconds();
|
||||
static int getNetworkHandlerDispatchQueueSize();
|
||||
static int getMaxTCPRetries();
|
||||
static int getMaxConnectionsPerIP();
|
||||
static bool getLogSendingTooMuchData();
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "sharedNetwork/UdpLibraryMT.h"
|
||||
#include "TcpClient.h"
|
||||
#include "TcpServer.h"
|
||||
#include "../../../../../../external/3rd/library/udplibrary/UdpLibrary.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -206,6 +207,7 @@ m_disconnectReason()
|
||||
p.clockSyncDelay = setup.clockSyncDelay;
|
||||
p.keepAliveDelay = setup.keepAliveDelay;
|
||||
p.maxConnections = 1;
|
||||
p.maxConnectionsPerIP = setup.maxConnectionsPerIP;
|
||||
p.maxRawPacketSize = setup.maxRawPacketSize;
|
||||
p.maxDataHoldSize = setup.maxDataHoldSize;
|
||||
p.reliable[0].maxInstandingPackets = setup.maxInstandingPackets;
|
||||
|
||||
@@ -18,6 +18,7 @@ outgoingBufferSize(ConfigSharedNetwork::getOutgoingBufferSize()),
|
||||
clockSyncDelay(ConfigSharedNetwork::getClockSyncDelay()),
|
||||
keepAliveDelay(ConfigSharedNetwork::getKeepAliveDelay()),
|
||||
maxConnections(ConfigSharedNetwork::getMaxConnections()),
|
||||
maxConnectionsPerIP(ConfigSharedNetwork::getMaxConnectionsPerIP()),
|
||||
maxRawPacketSize(ConfigSharedNetwork::getMaxRawPacketSize()),
|
||||
maxInstandingPackets(ConfigSharedNetwork::getMaxInstandingPackets()),
|
||||
maxOutstandingBytes(ConfigSharedNetwork::getMaxOutstandingBytes()),
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
int clockSyncDelay;
|
||||
int keepAliveDelay;
|
||||
int maxConnections;
|
||||
int maxConnectionsPerIP;
|
||||
int maxRawPacketSize;
|
||||
int maxInstandingPackets;
|
||||
int maxOutstandingBytes;
|
||||
|
||||
@@ -24,11 +24,10 @@ ConnectionAllocatorBase::~ConnectionAllocatorBase()
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//Service::Service(const ConnectionAllocatorBase & c, const unsigned short port, const int m, const int keepAliveDelay, const std::string & interfaceAddress, const bool compress) :
|
||||
Service::Service(const ConnectionAllocatorBase & c, const NetworkSetupData & setup, const int maxConnectionsPerIP) :
|
||||
Service::Service(const ConnectionAllocatorBase & c, const NetworkSetupData & setup) :
|
||||
connectionAllocator(c.clone()),
|
||||
m_callback(new MessageDispatch::Callback),
|
||||
m_tcpServer(0),
|
||||
m_maxConnectionsPerIP(maxConnectionsPerIP)
|
||||
m_tcpServer(0)
|
||||
{
|
||||
std::string realAddress;
|
||||
if(setup.bindInterface.length() > 0)
|
||||
@@ -93,12 +92,12 @@ m_maxConnectionsPerIP(maxConnectionsPerIP)
|
||||
p.icmpErrorRetryPeriod = setup.icmpErrorRetryPeriod;
|
||||
p.maxDataHoldSize = setup.maxDataHoldSize;
|
||||
p.allowPortRemapping = setup.allowPortRemapping;
|
||||
|
||||
p.maxConnectionsPerIP = setup.maxconnectionsPerIP;
|
||||
|
||||
if(realAddress.length() > 0)
|
||||
{
|
||||
strncpy(p.bindIpAddress, realAddress.c_str(), sizeof(p.bindIpAddress));
|
||||
}
|
||||
if (realAddress.length() > 0)
|
||||
{
|
||||
strncpy(p.bindIpAddress, realAddress.c_str(), sizeof(p.bindIpAddress));
|
||||
}
|
||||
|
||||
p.reliable[0].maxInstandingPackets = setup.maxInstandingPackets;
|
||||
p.reliable[0].maxOutstandingBytes = setup.maxOutstandingBytes;
|
||||
@@ -215,33 +214,11 @@ void Service::onConnectionOpened(Connection * c)
|
||||
{
|
||||
if (c)
|
||||
{
|
||||
if (connections.size() < static_cast<size_t>(m_maxConnections) || m_maxConnections == 0)
|
||||
if (connections.size() < static_cast<size_t>(m_maxConnections))
|
||||
{
|
||||
std::string remoteIP = c->getRemoteAddress();
|
||||
int numConnections = 0;
|
||||
|
||||
// if we're trying to throttle dos attempts
|
||||
if (m_maxConnectionsPerIP > 0)
|
||||
{
|
||||
// we have to recount each time so that we don't cut off legit users
|
||||
for (auto i = connections.begin(); i != connections.end(); ++i) {
|
||||
if (remoteIP == (*i)->getRemoteAddress()) {
|
||||
numConnections++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_maxConnectionsPerIP == 0 || (numConnections < m_maxConnectionsPerIP))
|
||||
{
|
||||
c->setService(this);
|
||||
c->onConnectionOpened();
|
||||
connections.insert(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING(true, ("Client at IP %s has attempted more connections than allowed (%i). Potential DoS Attack?", remoteIP.c_str(), m_maxConnectionsPerIP));
|
||||
removeConnection(c); // asshole (probably)
|
||||
}
|
||||
c->setService(this);
|
||||
c->onConnectionOpened();
|
||||
connections.insert(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ class Service : public NetworkHandler
|
||||
{
|
||||
public:
|
||||
//Service(const ConnectionAllocatorBase & connectionAllocator, const unsigned short listenPort, const int maxConnections, const int keepAliveDelay = 1000, const std::string & interfaceAddress = std::string(""), const bool compress=false);
|
||||
Service(const ConnectionAllocatorBase & connectionAllocator, const NetworkSetupData & setupData, const int maxConnectionsPerIP = 0);
|
||||
Service(const ConnectionAllocatorBase & connectionAllocator, const NetworkSetupData & setupData);
|
||||
virtual ~Service();
|
||||
|
||||
void onConnectionOpened(TcpClient * t);
|
||||
@@ -86,7 +86,6 @@ private:
|
||||
const ConnectionAllocatorBase * connectionAllocator;
|
||||
std::set<Connection *> connections;
|
||||
int m_maxConnections;
|
||||
int m_maxConnectionsPerIP; // dos protection for ping and login servers
|
||||
MessageDispatch::Callback * m_callback;
|
||||
TcpServer * m_tcpServer;
|
||||
};
|
||||
|
||||
+24
@@ -174,6 +174,7 @@ UdpManager::Params::Params()
|
||||
portAliveDelay = 0;
|
||||
noDataTimeout = 0;
|
||||
maxConnections = 10;
|
||||
maxConnectionsPerIP = 0;
|
||||
port = 0;
|
||||
portRange = 0;
|
||||
pooledPacketMax = 1000;
|
||||
@@ -997,8 +998,31 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
// connection establish packet must always be at least 6 bytes long as we must have a version number, no matter how it changes
|
||||
if (e->mBuffer[0] == 0 && e->mBuffer[1] == UdpConnection::cUdpPacketConnect && e->mLen == UdpConnection::cUdpPacketConnectSize)
|
||||
{
|
||||
if (mParams.maxConnectionsPerIP > 0)
|
||||
{
|
||||
UdpConnection *alreadyExists;
|
||||
|
||||
int clientConnections = 0;
|
||||
for (int i = 1; i != 65535; i++)
|
||||
{
|
||||
alreadyExists = AddressGetConnection(e->mIp, i);
|
||||
if (alreadyExists != nullptr)
|
||||
{
|
||||
clientConnections++;
|
||||
}
|
||||
}
|
||||
|
||||
if (clientConnections >= mParams.maxConnectionsPerIP)
|
||||
{
|
||||
printf("Possible DoS attempt? Client %i attempted more connections than the limit (%i). Dropping!", e->mIp, mParams.maxConnectionsPerIP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mConnectionListCount >= mParams.maxConnections)
|
||||
{
|
||||
return; // can't handle any more connections, so ignore this request entirely
|
||||
}
|
||||
|
||||
int protocolVersion = UdpMisc::GetValue32(e->mBuffer + 2);
|
||||
if (protocolVersion == cProtocolVersion)
|
||||
|
||||
+1
-1
@@ -482,7 +482,7 @@ class UdpManager
|
||||
// is little harm in setting this number larger.
|
||||
// default = 10
|
||||
int maxConnections;
|
||||
|
||||
int maxConnectionsPerIP;
|
||||
// this is the port number that this manager will use for all incoming and outgoing data. On the client side
|
||||
// this is typically set to 0, which causes the manager object to randomly pick an available port. On the server
|
||||
// side, this port should be set to a specific value as it will represent the port number that clients will use
|
||||
|
||||
Reference in New Issue
Block a user