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:
DarthArgus
2016-09-26 06:27:53 +00:00
parent 41639d8156
commit e395177e8f
10 changed files with 50 additions and 37 deletions
@@ -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
View File
@@ -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
View File
@@ -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