mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +00:00
refactor dos protection
This commit is contained in:
parent
df308c1dc5
commit
bc5e407d60
@ -35,6 +35,7 @@ set(PRJ_HEADERS
|
||||
include/Json.h
|
||||
include/LuaAPI.h
|
||||
include/RWMutex.h
|
||||
include/RateLimiter.h
|
||||
include/SignalHandling.h
|
||||
include/TConfig.h
|
||||
include/TConsole.h
|
||||
@ -72,6 +73,7 @@ set(PRJ_SOURCES
|
||||
src/TResourceManager.cpp
|
||||
src/TScopedTimer.cpp
|
||||
src/TServer.cpp
|
||||
src/RateLimiter.cpp
|
||||
src/VehicleData.cpp
|
||||
src/Env.cpp
|
||||
src/Profiling.cpp
|
||||
|
@ -27,14 +27,6 @@
|
||||
|
||||
struct TConnection;
|
||||
|
||||
class WatchingConnecting{
|
||||
public:
|
||||
bool IsConnectionAllowed(const std::string& clientAddress);
|
||||
private:
|
||||
void BlockIP(const std::string& clientAddress);
|
||||
bool IsIPBlocked(const std::string& clientAddress);
|
||||
};
|
||||
|
||||
class TNetwork {
|
||||
public:
|
||||
TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "Client.h"
|
||||
#include "Common.h"
|
||||
#include "LuaAPI.h"
|
||||
#include "RateLimiter.h"
|
||||
#include "TLuaEngine.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <CustomAssert.h>
|
||||
@ -31,63 +32,6 @@
|
||||
|
||||
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option;
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
std::unordered_map<std::string, std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>>> connectionAttempts;
|
||||
std::mutex connectionAttemptsMutex;
|
||||
|
||||
bool WatchingConnecting::IsConnectionAllowed(const std::string& clientAddress) {
|
||||
// we check if there is an IP in the blocked list
|
||||
if (WatchingConnecting::IsIPBlocked(clientAddress)) {
|
||||
return false;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(connectionAttemptsMutex);
|
||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||
auto& violations = connectionAttempts[clientAddress];
|
||||
|
||||
// Deleting old violations (older than 5 seconds)
|
||||
violations.erase(std::remove_if(violations.begin(), violations.end(),
|
||||
[&](const auto& timestamp) {
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(currentTime - timestamp).count() > 5;
|
||||
}), violations.end());
|
||||
|
||||
// Adding the current violation
|
||||
violations.push_back(currentTime);
|
||||
|
||||
// We check the number of violations
|
||||
if (violations.size() >= 4) {
|
||||
WatchingConnecting::BlockIP(clientAddress);
|
||||
beammp_errorf("[DOS] Blocked IP: {}", clientAddress);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // We allow the connection
|
||||
}
|
||||
|
||||
void WatchingConnecting::BlockIP(const std::string& clientAddress) {
|
||||
std::ofstream blockFile("blocked_ips.txt", std::ios::app);
|
||||
if (blockFile.is_open()) {
|
||||
blockFile << clientAddress << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool WatchingConnecting::IsIPBlocked(const std::string& clientAddress) {
|
||||
std::ifstream blockFile("blocked_ips.txt");
|
||||
std::unordered_set<std::string> blockedIPs;
|
||||
|
||||
if (blockFile.is_open()) {
|
||||
std::string line;
|
||||
while (std::getline(blockFile, line)) {
|
||||
blockedIPs.insert(line);
|
||||
}
|
||||
}
|
||||
return blockedIPs.find(clientAddress) != blockedIPs.end();
|
||||
};
|
||||
|
||||
std::vector<uint8_t> StringToVector(const std::string& Str) {
|
||||
return std::vector<uint8_t>(Str.data(), Str.data() + Str.size());
|
||||
}
|
||||
@ -253,16 +197,18 @@ void TNetwork::Identify(TConnection&& RawConnection) {
|
||||
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
||||
return;
|
||||
}
|
||||
std::string clientAddress = RawConnection.SockAddr.address().to_string();
|
||||
std::shared_ptr<TClient> Client { nullptr };
|
||||
WatchingConnecting connectionManager;
|
||||
std::string client_address = RawConnection.SockAddr.address().to_string();
|
||||
std::shared_ptr<TClient> client { nullptr };
|
||||
RateLimiter ddos_protection;
|
||||
try {
|
||||
if (Code == 'C') {
|
||||
if (connectionManager.IsConnectionAllowed(clientAddress)) {
|
||||
Client = Authentication(std::move(RawConnection));
|
||||
} else {
|
||||
if (ddos_protection.isConnectionAllowed(client_address)) {
|
||||
beammp_infof("[DoS Protection] Client: [{}] is authorized to connect to the server", client_address);
|
||||
client = Authentication(std::move(RawConnection));
|
||||
} else {
|
||||
beammp_infof("[DoS Protection] Client: [{}] has been denied access to the server", client_address);
|
||||
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
||||
}
|
||||
}
|
||||
} else if (Code == 'D') {
|
||||
HandleDownload(std::move(RawConnection));
|
||||
} else if (Code == 'P') {
|
||||
@ -452,7 +398,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!NotAllowedWithReason && !Application::Settings.AllowGuests && Client->IsGuest()) { //!NotAllowedWithReason because this message has the lowest priority
|
||||
if (!NotAllowedWithReason && !Application::Settings.AllowGuests && Client->IsGuest()) { //! NotAllowedWithReason because this message has the lowest priority
|
||||
NotAllowedWithReason = true;
|
||||
Reason = "No guests are allowed on this server! To join, sign up at: forum.beammp.com.";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user