mirror of
https://github.com/GOSTSec/poolserver
synced 2025-01-14 08:47:53 +00:00
DoS protection
This commit is contained in:
parent
0fccd298c6
commit
d504129cb7
@ -9,6 +9,22 @@
|
||||
|
||||
namespace Stratum
|
||||
{
|
||||
void Client::Start()
|
||||
{
|
||||
// Get IP
|
||||
tcp::endpoint remote_ep = _socket.remote_endpoint();
|
||||
address remote_ad = remote_ep.address();
|
||||
_ip = remote_ad.to_v4().to_ulong();
|
||||
|
||||
if (_server->IsBanned(_ip)) {
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start reading socket
|
||||
StartRead();
|
||||
}
|
||||
|
||||
void Client::SendJob(bool clean)
|
||||
{
|
||||
if (clean)
|
||||
@ -92,6 +108,7 @@ namespace Stratum
|
||||
// Check if such job exists
|
||||
if (!_jobs.count(jobid)) {
|
||||
DataMgr::Instance()->Push(Share(_ip, username, false, "Job not found", Util::Date(), 1));
|
||||
_shareLimiter.LogBad();
|
||||
|
||||
JSON response;
|
||||
response["id"] = msg["id"];
|
||||
@ -150,6 +167,7 @@ namespace Stratum
|
||||
if (!job.SubmitShare(share.Binary())) {
|
||||
sLog.Error(LOG_SERVER, "Duplicate share");
|
||||
DataMgr::Instance()->Push(Share(_ip, username, false, "Duplicate share", Util::Date(), job.diff));
|
||||
_shareLimiter.LogBad();
|
||||
|
||||
JSON response;
|
||||
response["id"] = msg["id"];
|
||||
@ -198,6 +216,7 @@ namespace Stratum
|
||||
if (target > Bitcoin::DiffToTarget(job.diff)) {
|
||||
sLog.Error(LOG_SERVER, "Share above target");
|
||||
DataMgr::Instance()->Push(Share(_ip, username, false, "Share above target", Util::Date(), job.diff));
|
||||
_shareLimiter.LogBad();
|
||||
|
||||
JSON response;
|
||||
response["id"] = msg["id"];
|
||||
@ -213,7 +232,11 @@ namespace Stratum
|
||||
if (target <= criteria) {
|
||||
sLog.Info(LOG_SERVER, "We have found a block candidate!");
|
||||
|
||||
_server->SubmitBlock(block);
|
||||
if (_server->SubmitBlock(block)) {
|
||||
std::string query("INSERT INTO `shares` (`rem_host`, `username`, `our_result`, `upstream_result`, `reason`, `solution`, `time`, `difficulty`) VALUES ");
|
||||
query += Util::FS("(INET_NTOA(%u), '%s', 1, 1, '', '%s', FROM_UNIXTIME(%u), %u)", _ip, username.c_str(), Util::BinToASCII(hash).c_str(), Util::Date(), job.diff);
|
||||
sDatabase.ExecuteAsync(query.c_str());
|
||||
}
|
||||
} else {
|
||||
DataMgr::Instance()->Push(Share(_ip, username, true, "", Util::Date(), job.diff));
|
||||
|
||||
@ -304,6 +327,17 @@ namespace Stratum
|
||||
return job;
|
||||
}
|
||||
|
||||
void Client::Ban(uint32 time)
|
||||
{
|
||||
_server->Ban(_ip, time);
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
void Client::Disconnect()
|
||||
{
|
||||
_server->Disconnect(shared_from_this());
|
||||
}
|
||||
|
||||
void Client::_OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
|
||||
{
|
||||
if (!error) {
|
||||
@ -334,7 +368,7 @@ namespace Stratum
|
||||
} else {
|
||||
// Client disconnected
|
||||
if ((error == asio::error::eof) || (error == asio::error::connection_reset)) {
|
||||
_server->Disconnect(shared_from_this());
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,16 +38,8 @@ namespace Stratum
|
||||
return _socket;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Get IP
|
||||
tcp::endpoint remote_ep = _socket.remote_endpoint();
|
||||
address remote_ad = remote_ep.address();
|
||||
_ip = remote_ad.to_v4().to_ulong();
|
||||
|
||||
// Start reading socket
|
||||
StartRead();
|
||||
}
|
||||
// Start client up!
|
||||
void Start();
|
||||
|
||||
void StartRead()
|
||||
{
|
||||
@ -124,7 +116,10 @@ namespace Stratum
|
||||
return _id;
|
||||
}
|
||||
|
||||
void Disconnect()
|
||||
void Ban(uint32 time);
|
||||
void Disconnect();
|
||||
|
||||
void CloseSocket()
|
||||
{
|
||||
_socket.close();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost;
|
||||
using namespace boost::asio::ip;
|
||||
@ -28,6 +29,12 @@ namespace Stratum
|
||||
uint16 Port;
|
||||
};
|
||||
|
||||
struct BanInfo
|
||||
{
|
||||
uint32 ip;
|
||||
uint64 timestamp;
|
||||
};
|
||||
|
||||
// Used for sorting std::set
|
||||
struct ClientPtrCMP
|
||||
{
|
||||
@ -95,6 +102,26 @@ namespace Stratum
|
||||
_clients.erase(client);
|
||||
}
|
||||
|
||||
void Ban(uint32 ip, uint64 time)
|
||||
{
|
||||
BanInfo ban;
|
||||
ban.ip = ip;
|
||||
ban.timestamp = Util::Date() + time;
|
||||
_bans.push_back(ban);
|
||||
}
|
||||
|
||||
bool IsBanned(uint32 ip)
|
||||
{
|
||||
for (int i = 0; i < _bans.size(); ++i) {
|
||||
if (_bans[i].ip == ip) {
|
||||
if (_bans[i].timestamp > Util::Date())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void _StartAccept()
|
||||
{
|
||||
@ -123,6 +150,7 @@ namespace Stratum
|
||||
|
||||
// Clients
|
||||
std::set<ClientPtr, ClientPtrCMP> _clients;
|
||||
std::vector<BanInfo> _bans;
|
||||
uint64 _clientId;
|
||||
|
||||
// Work
|
||||
|
@ -8,6 +8,8 @@ namespace Stratum
|
||||
// Returning false will stop any further share verifications (DoS prevention, etc)
|
||||
bool ShareLimiter::Submit()
|
||||
{
|
||||
++_totalShares;
|
||||
|
||||
uint64 curTime = Util::Date();
|
||||
uint64 sinceLast = curTime - _lastRetarget;
|
||||
|
||||
@ -18,6 +20,10 @@ namespace Stratum
|
||||
|
||||
_lastRetarget = curTime;
|
||||
|
||||
// Check if miner is ok
|
||||
if (_totalShares > 20 && (double(_totalBadShares)/double(_totalShares)) > 0.8)
|
||||
_client->Ban(60);
|
||||
|
||||
while (_shares.size() && (_shares.front() < curTime - RETARGET_TIME_BUFFER))
|
||||
_shares.pop_front();
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace Stratum
|
||||
class ShareLimiter
|
||||
{
|
||||
public:
|
||||
ShareLimiter(Client* client) : _client(client)
|
||||
ShareLimiter(Client* client) : _client(client), _totalShares(0), _totalBadShares(0)
|
||||
{
|
||||
_startTime = Util::Date();
|
||||
_lastRetarget = _startTime;
|
||||
@ -27,11 +27,19 @@ namespace Stratum
|
||||
|
||||
bool Submit();
|
||||
|
||||
void LogBad()
|
||||
{
|
||||
++_totalBadShares;
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<uint64> _shares;
|
||||
Client* _client;
|
||||
uint64 _lastRetarget;
|
||||
uint64 _startTime;
|
||||
|
||||
uint64 _totalShares;
|
||||
uint64 _totalBadShares;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user