refactor dos protection

This commit is contained in:
sla-ppy
2024-06-20 07:28:55 +02:00
parent df308c1dc5
commit bc5e407d60
3 changed files with 15 additions and 75 deletions

View File

@@ -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 (Code == 'C') {
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') {
@@ -355,7 +301,7 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
std::string Key(reinterpret_cast<const char*>(Data.data()), Data.size());
std::string AuthKey = Application::Settings.Key;
std::string ClientIp = Client->GetIdentifiers().at("ip");
nlohmann::json AuthReq {};
std::string AuthResStr {};
try {
@@ -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.";
}