mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
implement proper blacklisting at the lowest possible level, with strikes so that people repeatedly hitting enter with connection issues don't get insta banned
This commit is contained in:
+57
-18
@@ -4,6 +4,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ios>
|
||||
#include <fstream>
|
||||
|
||||
#include "UdpLibrary.hpp"
|
||||
|
||||
#if defined(WIN32)
|
||||
@@ -39,8 +43,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/ip_icmp.h> // needed by gcc 3.1 for linux
|
||||
#include <ios>
|
||||
#include <fstream>
|
||||
|
||||
const int INVALID_SOCKET = 0xFFFFFFFF;
|
||||
const int SOCKET_ERROR = 0xFFFFFFFF;
|
||||
@@ -408,8 +410,10 @@ UdpManager::~UdpManager()
|
||||
|
||||
delete mAddressHashTable;
|
||||
mIpConnectionCount.clear();
|
||||
blacklist.clear();
|
||||
delete mConnectCodeHashTable;
|
||||
delete mPriorityQueue;
|
||||
|
||||
for (int i = 0; i < mParams.packetHistoryMax; i++)
|
||||
{
|
||||
delete mPacketHistory[i];
|
||||
@@ -818,15 +822,22 @@ UdpManager::PacketHistoryEntry *UdpManager::ActualReceive()
|
||||
|
||||
if (res != SOCKET_ERROR)
|
||||
{
|
||||
if (mParams.simulateIncomingLossPercent > 0 && ((rand() % 100) < mParams.simulateIncomingLossPercent))
|
||||
return(nullptr); // packet, what packet?
|
||||
// no need in creating objects or processing anything if they are a DoS Attacker!
|
||||
if (isBlacklisted(addr_from.sin_addr.s_addr))
|
||||
{
|
||||
return nullptr; // send them to the black hole
|
||||
}
|
||||
|
||||
if (mParams.simulateIncomingByteRate > 0)
|
||||
mSimulateNextIncomingTime = UdpMisc::Clock() + (res * 1000 / mParams.simulateIncomingByteRate);
|
||||
if (mParams.simulateIncomingLossPercent > 0 && ((rand() % 100) < mParams.simulateIncomingLossPercent))
|
||||
return(nullptr); // packet, what packet?
|
||||
|
||||
mLastReceiveTime = UdpMisc::Clock();
|
||||
mPacketHistory[pos]->mLen = res;
|
||||
if (mParams.simulateIncomingByteRate > 0)
|
||||
mSimulateNextIncomingTime = UdpMisc::Clock() + (res * 1000 / mParams.simulateIncomingByteRate);
|
||||
|
||||
|
||||
mLastReceiveTime = UdpMisc::Clock();
|
||||
mPacketHistory[pos]->mIp = UdpIpAddress(addr_from.sin_addr.s_addr);
|
||||
mPacketHistory[pos]->mLen = res;
|
||||
mPacketHistory[pos]->mPort = (int)ntohs(addr_from.sin_port);
|
||||
|
||||
mPacketHistoryPosition = (mPacketHistoryPosition + 1) % mParams.packetHistoryMax;
|
||||
@@ -1023,23 +1034,33 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
{
|
||||
if (mParams.maxConnectionsPerIP > 0)
|
||||
{
|
||||
if (mIpConnectionCount[e->mIp.GetAddress()] >= mParams.maxConnectionsPerIP)
|
||||
unsigned int clientAddr = e->mIp.GetAddress();
|
||||
|
||||
if (mIpConnectionCount[clientAddr] >= mParams.maxConnectionsPerIP)
|
||||
{
|
||||
std::ofstream log_file("logs/udpDos.log", std::ios_base::out | std::ios_base::app );
|
||||
log_file << "UdpLibrary : Potential DoS Attack! Client at IP " << e->mIp.GetV4Address() << " tried to exceed maxConnectionsPerIP (" << mParams.maxConnectionsPerIP << "). Silently disconnecting.\n" << std::end;
|
||||
if (!isBlacklisted(clientAddr))
|
||||
{
|
||||
// add a strike - if they hit strikeOut then they're banned til next restart
|
||||
blacklist[clientAddr]++;
|
||||
|
||||
con->InternalDisconnect(0, UdpConnection::cDisconnectDosAsshole);
|
||||
con->SetSilentDisconnect(true); // screw you, jerk
|
||||
con->Release();
|
||||
// log it - later parse this, cross reference, and block in iptables
|
||||
extern const char *__progname;
|
||||
const std::string prog(__progname);
|
||||
static const std::string filename = "logs/udpDos-" + prog + ".log";
|
||||
|
||||
std::ofstream log_file(filename, std::ios_base::out | std::ios_base::app );
|
||||
log_file << "Ignoring potential DoS attack from " << e->mIp.GetV4Address() << " (strike " << blacklist[clientAddr] << " of " << strikeOut << ")\n";
|
||||
log_file.close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mConnectionListCount >= mParams.maxConnections)
|
||||
{
|
||||
return; // can't handle any more connections, so ignore this request entirely
|
||||
}
|
||||
{
|
||||
return; // can't handle any more connections, so ignore this request entirely
|
||||
}
|
||||
|
||||
int protocolVersion = UdpMisc::GetValue32(e->mBuffer + 2);
|
||||
if (protocolVersion == cProtocolVersion)
|
||||
@@ -1120,6 +1141,24 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
con->Release();
|
||||
}
|
||||
|
||||
bool UdpManager::isBlacklisted(unsigned int clientAddr)
|
||||
{
|
||||
return (blacklist[clientAddr] == strikeOut);
|
||||
}
|
||||
|
||||
void UdpManager::disconnectByIp(unsigned int clientAddr)
|
||||
{
|
||||
while (mConnectionList != nullptr)
|
||||
{
|
||||
if (mConnectionList->mIp.GetAddress() == clientAddr)
|
||||
{
|
||||
mConnectionList->SetSilentDisconnect(true);
|
||||
mConnectionList->InternalDisconnect(0, UdpConnection::cDisconnectReasonDosAttack);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UdpConnection *UdpManager::AddressGetConnection(UdpIpAddress ip, int port) const
|
||||
{
|
||||
UdpConnection *found = static_cast<UdpConnection *>(mAddressHashTable->FindFirst(AddressHashValue(ip, port)));
|
||||
@@ -2939,7 +2978,7 @@ const char *UdpConnection::DisconnectReasonText(DisconnectReason reason)
|
||||
sDisconnectReason[cDisconnectReasonMutualConnectError] = "DisconnectReasonConnectError";
|
||||
sDisconnectReason[cDisconnectReasonConnectingToSelf] = "DisconnectReasonConnectingToSelf";
|
||||
sDisconnectReason[cDisconnectReasonReliableOverflow] = "DisconnectReasonReliableOverflow";
|
||||
sDisconnectReason[cDisconnectDosAsshole] = "DisconnectAssholeDosAttempt";
|
||||
sDisconnectReason[cDisconnectReasonDosAttack] = "DisconnectReasonDoSAttack";
|
||||
}
|
||||
|
||||
return(sDisconnectReason[reason]);
|
||||
|
||||
+17
-1
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "UdpHandler.hpp"
|
||||
#include "priority.hpp"
|
||||
#include "hashtable.hpp"
|
||||
@@ -925,6 +926,9 @@ class UdpManager
|
||||
// to explicitly call this function.
|
||||
LogicalPacket *CreatePacket(const void *data, int dataLen, const void *data2 = nullptr, int dataLen2 = 0);
|
||||
|
||||
// is the given unsigned int expressed ip blacklisted?
|
||||
bool isBlacklisted(unsigned int);
|
||||
|
||||
protected:
|
||||
friend class PooledLogicalPacket;
|
||||
void PoolReturn(PooledLogicalPacket *packet); // so pooled packets can add themselves back to the pool
|
||||
@@ -1041,7 +1045,19 @@ class UdpManager
|
||||
// typically it is recommended that all UdpConnection objects be destroyed before destroying this manager object
|
||||
|
||||
int mRefCount;
|
||||
|
||||
// number of strikes
|
||||
static const int strikeOut = 3;
|
||||
|
||||
// actual count of connections for a given ip
|
||||
std::unordered_map<unsigned int, int> mIpConnectionCount;
|
||||
|
||||
|
||||
// count of strikes against a given ip - 3 successive DoS attempts and they are banned til next restart at best
|
||||
std::unordered_map<unsigned int, int> blacklist;
|
||||
|
||||
// does what it says
|
||||
void disconnectByIp (unsigned int);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1059,7 +1075,7 @@ class UdpConnection : public PriorityQueueMember, public AddressHashTableMember,
|
||||
, cDisconnectReasonNewConnectionAttempt, cDisconnectReasonConnectionRefused
|
||||
, cDisconnectReasonMutualConnectError, cDisconnectReasonConnectingToSelf
|
||||
, cDisconnectReasonReliableOverflow
|
||||
, cDisconnectReasonCount, cDisconnectDosAsshole };
|
||||
, cDisconnectReasonCount, cDisconnectReasonDosAttack };
|
||||
|
||||
// standard AddRef/Release scheme
|
||||
void AddRef();
|
||||
|
||||
Reference in New Issue
Block a user