Browse Source

DoS protection

master
Intel 10 years ago
parent
commit
d504129cb7
  1. 38
      src/server/poolserver/Stratum/Client.cpp
  2. 17
      src/server/poolserver/Stratum/Client.h
  3. 28
      src/server/poolserver/Stratum/Server.h
  4. 6
      src/server/poolserver/Stratum/ShareLimiter.cpp
  5. 10
      src/server/poolserver/Stratum/ShareLimiter.h

38
src/server/poolserver/Stratum/Client.cpp

@ -9,6 +9,22 @@ @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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();
}
}
}

17
src/server/poolserver/Stratum/Client.h

@ -38,16 +38,8 @@ namespace Stratum @@ -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 @@ -124,7 +116,10 @@ namespace Stratum
return _id;
}
void Disconnect()
void Ban(uint32 time);
void Disconnect();
void CloseSocket()
{
_socket.close();
}

28
src/server/poolserver/Stratum/Server.h

@ -16,6 +16,7 @@ @@ -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 @@ -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 @@ -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 @@ -123,6 +150,7 @@ namespace Stratum
// Clients
std::set<ClientPtr, ClientPtrCMP> _clients;
std::vector<BanInfo> _bans;
uint64 _clientId;
// Work

6
src/server/poolserver/Stratum/ShareLimiter.cpp

@ -8,6 +8,8 @@ namespace Stratum @@ -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 @@ -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();

10
src/server/poolserver/Stratum/ShareLimiter.h

@ -19,7 +19,7 @@ namespace Stratum @@ -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 @@ -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…
Cancel
Save