mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 18:24:16 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70967a81a3 | |||
| 93a477e9c3 | |||
| 2c05a442ee |
@@ -35,6 +35,7 @@ set(PRJ_HEADERS
|
|||||||
include/Json.h
|
include/Json.h
|
||||||
include/LuaAPI.h
|
include/LuaAPI.h
|
||||||
include/RWMutex.h
|
include/RWMutex.h
|
||||||
|
include/RateLimiter.h
|
||||||
include/SignalHandling.h
|
include/SignalHandling.h
|
||||||
include/TConfig.h
|
include/TConfig.h
|
||||||
include/TConsole.h
|
include/TConsole.h
|
||||||
@@ -72,6 +73,7 @@ set(PRJ_SOURCES
|
|||||||
src/TResourceManager.cpp
|
src/TResourceManager.cpp
|
||||||
src/TScopedTimer.cpp
|
src/TScopedTimer.cpp
|
||||||
src/TServer.cpp
|
src/TServer.cpp
|
||||||
|
src/RateLimiter.cpp
|
||||||
src/VehicleData.cpp
|
src/VehicleData.cpp
|
||||||
src/Env.cpp
|
src/Env.cpp
|
||||||
src/Profiling.cpp
|
src/Profiling.cpp
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include "Common.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
class RateLimiter {
|
||||||
|
public:
|
||||||
|
RateLimiter();
|
||||||
|
bool isConnectionAllowed(const std::string& client_address);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>>> m_connection;
|
||||||
|
std::mutex m_connection_mutex;
|
||||||
|
|
||||||
|
void blockIP(const std::string& client_address);
|
||||||
|
bool isIPBlocked(const std::string& client_address);
|
||||||
|
};
|
||||||
@@ -48,7 +48,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
void UDPServerMain();
|
void UDPServerMain();
|
||||||
void TCPServerMain();
|
void TCPServerMain();
|
||||||
|
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
TPPSMonitor& mPPSMonitor;
|
TPPSMonitor& mPPSMonitor;
|
||||||
ip::udp::socket mUDPSock;
|
ip::udp::socket mUDPSock;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#include "RateLimiter.h"
|
||||||
|
|
||||||
|
RateLimiter::RateLimiter() {};
|
||||||
|
|
||||||
|
bool RateLimiter::isConnectionAllowed(const std::string& client_address) {
|
||||||
|
if (RateLimiter::isIPBlocked(client_address)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||||
|
auto current_time = std::chrono::high_resolution_clock::now();
|
||||||
|
auto& violations = m_connection[client_address];
|
||||||
|
|
||||||
|
// 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>(current_time - timestamp).count() > 5;
|
||||||
|
}),
|
||||||
|
violations.end());
|
||||||
|
|
||||||
|
violations.push_back(current_time);
|
||||||
|
|
||||||
|
if (violations.size() >= 4) {
|
||||||
|
RateLimiter::blockIP(client_address);
|
||||||
|
beammp_errorf("[DoS Protection] Client with the IP: {} surpassed the violation treshhold and is now on the blocked list", client_address);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // We allow the connection
|
||||||
|
}
|
||||||
|
|
||||||
|
void RateLimiter::blockIP(const std::string& client_address) {
|
||||||
|
std::ofstream block_file("blocked_ips.txt", std::ios::app);
|
||||||
|
if (block_file.is_open()) {
|
||||||
|
block_file << client_address << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RateLimiter::isIPBlocked(const std::string& client_address) {
|
||||||
|
std::ifstream block_file("blocked_ips.txt");
|
||||||
|
std::unordered_set<std::string> blockedIPs;
|
||||||
|
|
||||||
|
if (block_file.is_open()) {
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(block_file, line)) {
|
||||||
|
blockedIPs.insert(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockedIPs.contains(client_address);
|
||||||
|
};
|
||||||
+12
-3
@@ -20,6 +20,7 @@
|
|||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "LuaAPI.h"
|
#include "LuaAPI.h"
|
||||||
|
#include "RateLimiter.h"
|
||||||
#include "TLuaEngine.h"
|
#include "TLuaEngine.h"
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
#include <CustomAssert.h>
|
#include <CustomAssert.h>
|
||||||
@@ -196,10 +197,18 @@ void TNetwork::Identify(TConnection&& RawConnection) {
|
|||||||
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::shared_ptr<TClient> Client { nullptr };
|
std::string client_address = RawConnection.SockAddr.address().to_string();
|
||||||
|
std::shared_ptr<TClient> client { nullptr };
|
||||||
|
RateLimiter ddos_protection;
|
||||||
try {
|
try {
|
||||||
if (Code == 'C') {
|
if (Code == 'C') {
|
||||||
Client = Authentication(std::move(RawConnection));
|
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') {
|
} else if (Code == 'D') {
|
||||||
HandleDownload(std::move(RawConnection));
|
HandleDownload(std::move(RawConnection));
|
||||||
} else if (Code == 'P') {
|
} else if (Code == 'P') {
|
||||||
@@ -389,7 +398,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
|
|||||||
return false;
|
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;
|
NotAllowedWithReason = true;
|
||||||
Reason = "No guests are allowed on this server! To join, sign up at: forum.beammp.com.";
|
Reason = "No guests are allowed on this server! To join, sign up at: forum.beammp.com.";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user