Browse Source

net: move ban and addrman functions into CConnman

0.14
Cory Fields 9 years ago
parent
commit
a0f3d3cdad
  1. 14
      src/main.cpp
  2. 126
      src/net.cpp
  3. 89
      src/net.h
  4. 3
      src/qt/bantablemodel.cpp
  5. 11
      src/qt/rpcconsole.cpp
  6. 17
      src/rpc/net.cpp
  7. 28
      src/test/DoS_tests.cpp

14
src/main.cpp

@ -4944,7 +4944,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->nServices = ServiceFlags(nServiceInt); pfrom->nServices = ServiceFlags(nServiceInt);
if (!pfrom->fInbound) if (!pfrom->fInbound)
{ {
addrman.SetServices(pfrom->addr, pfrom->nServices); connman.SetServices(pfrom->addr, pfrom->nServices);
} }
if (pfrom->nServicesExpected & ~pfrom->nServices) if (pfrom->nServicesExpected & ~pfrom->nServices)
{ {
@ -5038,12 +5038,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
} }
// Get recent addresses // Get recent addresses
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000) if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman.GetAddressCount() < 1000)
{ {
pfrom->PushMessage(NetMsgType::GETADDR); pfrom->PushMessage(NetMsgType::GETADDR);
pfrom->fGetAddr = true; pfrom->fGetAddr = true;
} }
addrman.Good(pfrom->addr); connman.MarkAddressGood(pfrom->addr);
} }
pfrom->fSuccessfullyConnected = true; pfrom->fSuccessfullyConnected = true;
@ -5108,7 +5108,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vRecv >> vAddr; vRecv >> vAddr;
// Don't want addr from older versions unless seeding // Don't want addr from older versions unless seeding
if (pfrom->nVersion < CADDR_TIME_VERSION && addrman.size() > 1000) if (pfrom->nVersion < CADDR_TIME_VERSION && connman.GetAddressCount() > 1000)
return true; return true;
if (vAddr.size() > 1000) if (vAddr.size() > 1000)
{ {
@ -5160,7 +5160,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (fReachable) if (fReachable)
vAddrOk.push_back(addr); vAddrOk.push_back(addr);
} }
addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); connman.AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60);
if (vAddr.size() < 1000) if (vAddr.size() < 1000)
pfrom->fGetAddr = false; pfrom->fGetAddr = false;
if (pfrom->fOneShot) if (pfrom->fOneShot)
@ -5950,7 +5950,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->fSentAddr = true; pfrom->fSentAddr = true;
pfrom->vAddrToSend.clear(); pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = addrman.GetAddr(); vector<CAddress> vAddr = connman.GetAddresses();
BOOST_FOREACH(const CAddress &addr, vAddr) BOOST_FOREACH(const CAddress &addr, vAddr)
pfrom->PushAddress(addr); pfrom->PushAddress(addr);
} }
@ -6393,7 +6393,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString()); LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
else else
{ {
CNode::Ban(pto->addr, BanReasonNodeMisbehaving); connman.Ban(pto->addr, BanReasonNodeMisbehaving);
} }
} }
state.fShouldBan = false; state.fShouldBan = false;

126
src/net.cpp

@ -84,9 +84,7 @@ std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfLimited[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL; static CNode* pnodeLocalHost = NULL;
uint64_t nLocalHostNonce = 0; uint64_t nLocalHostNonce = 0;
CAddrMan addrman;
int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
bool fAddressesInitialized = false;
std::string strSubVersion; std::string strSubVersion;
std::vector<CNode*> vNodes; std::vector<CNode*> vNodes;
@ -446,21 +444,21 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return NULL; return NULL;
} }
static void DumpBanlist() void CConnman::DumpBanlist()
{ {
CNode::SweepBanned(); // clean unused entries (if bantime has expired) SweepBanned(); // clean unused entries (if bantime has expired)
if (!CNode::BannedSetIsDirty()) if (!BannedSetIsDirty())
return; return;
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
CBanDB bandb; CBanDB bandb;
banmap_t banmap; banmap_t banmap;
CNode::SetBannedSetDirty(false); SetBannedSetDirty(false);
CNode::GetBanned(banmap); GetBanned(banmap);
if (!bandb.Write(banmap)) if (!bandb.Write(banmap))
CNode::SetBannedSetDirty(true); SetBannedSetDirty(true);
LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart); banmap.size(), GetTimeMillis() - nStart);
@ -501,11 +499,7 @@ void CNode::PushVersion()
banmap_t CNode::setBanned; void CConnman::ClearBanned()
CCriticalSection CNode::cs_setBanned;
bool CNode::setBannedIsDirty;
void CNode::ClearBanned()
{ {
{ {
LOCK(cs_setBanned); LOCK(cs_setBanned);
@ -516,7 +510,7 @@ void CNode::ClearBanned()
uiInterface.BannedListChanged(); uiInterface.BannedListChanged();
} }
bool CNode::IsBanned(CNetAddr ip) bool CConnman::IsBanned(CNetAddr ip)
{ {
bool fResult = false; bool fResult = false;
{ {
@ -533,7 +527,7 @@ bool CNode::IsBanned(CNetAddr ip)
return fResult; return fResult;
} }
bool CNode::IsBanned(CSubNet subnet) bool CConnman::IsBanned(CSubNet subnet)
{ {
bool fResult = false; bool fResult = false;
{ {
@ -549,12 +543,12 @@ bool CNode::IsBanned(CSubNet subnet)
return fResult; return fResult;
} }
void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
CSubNet subNet(addr); CSubNet subNet(addr);
Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch); Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
} }
void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
CBanEntry banEntry(GetTime()); CBanEntry banEntry(GetTime());
banEntry.banReason = banReason; banEntry.banReason = banReason;
if (bantimeoffset <= 0) if (bantimeoffset <= 0)
@ -585,12 +579,12 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti
DumpBanlist(); //store banlist to disk immediately if user requested ban DumpBanlist(); //store banlist to disk immediately if user requested ban
} }
bool CNode::Unban(const CNetAddr &addr) { bool CConnman::Unban(const CNetAddr &addr) {
CSubNet subNet(addr); CSubNet subNet(addr);
return Unban(subNet); return Unban(subNet);
} }
bool CNode::Unban(const CSubNet &subNet) { bool CConnman::Unban(const CSubNet &subNet) {
{ {
LOCK(cs_setBanned); LOCK(cs_setBanned);
if (!setBanned.erase(subNet)) if (!setBanned.erase(subNet))
@ -602,20 +596,20 @@ bool CNode::Unban(const CSubNet &subNet) {
return true; return true;
} }
void CNode::GetBanned(banmap_t &banMap) void CConnman::GetBanned(banmap_t &banMap)
{ {
LOCK(cs_setBanned); LOCK(cs_setBanned);
banMap = setBanned; //create a thread safe copy banMap = setBanned; //create a thread safe copy
} }
void CNode::SetBanned(const banmap_t &banMap) void CConnman::SetBanned(const banmap_t &banMap)
{ {
LOCK(cs_setBanned); LOCK(cs_setBanned);
setBanned = banMap; setBanned = banMap;
setBannedIsDirty = true; setBannedIsDirty = true;
} }
void CNode::SweepBanned() void CConnman::SweepBanned()
{ {
int64_t now = GetTime(); int64_t now = GetTime();
@ -636,13 +630,13 @@ void CNode::SweepBanned()
} }
} }
bool CNode::BannedSetIsDirty() bool CConnman::BannedSetIsDirty()
{ {
LOCK(cs_setBanned); LOCK(cs_setBanned);
return setBannedIsDirty; return setBannedIsDirty;
} }
void CNode::SetBannedSetDirty(bool dirty) void CConnman::SetBannedSetDirty(bool dirty)
{ {
LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag
setBannedIsDirty = dirty; setBannedIsDirty = dirty;
@ -1047,7 +1041,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int)); setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int));
#endif #endif
if (CNode::IsBanned(addr) && !whitelisted) if (IsBanned(addr) && !whitelisted)
{ {
LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
CloseSocket(hSocket); CloseSocket(hSocket);
@ -1548,7 +1542,7 @@ void CConnman::ThreadDNSAddressSeed()
void DumpAddresses() void CConnman::DumpAddresses()
{ {
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
@ -1559,7 +1553,7 @@ void DumpAddresses()
addrman.size(), GetTimeMillis() - nStart); addrman.size(), GetTimeMillis() - nStart);
} }
void DumpData() void CConnman::DumpData()
{ {
DumpAddresses(); DumpAddresses();
DumpBanlist(); DumpBanlist();
@ -1813,7 +1807,7 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
if (!pszDest) { if (!pszDest) {
if (IsLocal(addrConnect) || if (IsLocal(addrConnect) ||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || FindNode((CNetAddr)addrConnect) || IsBanned(addrConnect) ||
FindNode(addrConnect.ToStringIPPort())) FindNode(addrConnect.ToStringIPPort()))
return false; return false;
} else if (FindNode(std::string(pszDest))) } else if (FindNode(std::string(pszDest)))
@ -2054,10 +2048,22 @@ void static Discover(boost::thread_group& threadGroup)
CConnman::CConnman() CConnman::CConnman()
{ {
setBannedIsDirty = false;
fAddressesInitialized = false;
} }
bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError)
{ {
Discover(threadGroup);
bool ret = connman.Start(threadGroup, scheduler, strNodeError);
return ret;
}
bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError)
{
uiInterface.InitMessage(_("Loading addresses...")); uiInterface.InitMessage(_("Loading addresses..."));
// Load addresses from peers.dat // Load addresses from peers.dat
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
@ -2078,15 +2084,15 @@ bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler&
CBanDB bandb; CBanDB bandb;
banmap_t banmap; banmap_t banmap;
if (bandb.Read(banmap)) { if (bandb.Read(banmap)) {
CNode::SetBanned(banmap); // thread save setter SetBanned(banmap); // thread save setter
CNode::SetBannedSetDirty(false); // no need to write down, just read data SetBannedSetDirty(false); // no need to write down, just read data
CNode::SweepBanned(); // sweep out unused entries SweepBanned(); // sweep out unused entries
LogPrint("net", "Loaded %d banned node ips/subnets from banlist.dat %dms\n", LogPrint("net", "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart); banmap.size(), GetTimeMillis() - nStart);
} else { } else {
LogPrintf("Invalid or missing banlist.dat; recreating\n"); LogPrintf("Invalid or missing banlist.dat; recreating\n");
CNode::SetBannedSetDirty(true); // force write SetBannedSetDirty(true); // force write
DumpBanlist(); DumpBanlist();
} }
@ -2094,17 +2100,6 @@ bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler&
fAddressesInitialized = true; fAddressesInitialized = true;
Discover(threadGroup);
bool ret = connman.Start(threadGroup, strNodeError);
// Dump network addresses
scheduler.scheduleEvery(DumpData, DUMP_ADDRESSES_INTERVAL);
return ret;
}
bool CConnman::Start(boost::thread_group& threadGroup, std::string& strNodeError)
{
if (semOutbound == NULL) { if (semOutbound == NULL) {
// initialize semaphore // initialize semaphore
int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections); int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections);
@ -2142,6 +2137,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, std::string& strNodeError
// Process messages // Process messages
threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "msghand", boost::function<void()>(boost::bind(&CConnman::ThreadMessageHandler, this)))); threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "msghand", boost::function<void()>(boost::bind(&CConnman::ThreadMessageHandler, this))));
// Dump network addresses
scheduler.scheduleEvery(boost::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL);
return true; return true;
} }
@ -2150,12 +2148,6 @@ bool StopNode(CConnman& connman)
LogPrintf("StopNode()\n"); LogPrintf("StopNode()\n");
MapPort(false); MapPort(false);
if (fAddressesInitialized)
{
DumpData();
fAddressesInitialized = false;
}
connman.Stop(); connman.Stop();
return true; return true;
} }
@ -2181,6 +2173,12 @@ void CConnman::Stop()
for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++)
semOutbound->post(); semOutbound->post();
if (fAddressesInitialized)
{
DumpData();
fAddressesInitialized = false;
}
// Close sockets // Close sockets
BOOST_FOREACH(CNode* pnode, vNodes) BOOST_FOREACH(CNode* pnode, vNodes)
if (pnode->hSocket != INVALID_SOCKET) if (pnode->hSocket != INVALID_SOCKET)
@ -2221,6 +2219,36 @@ CConnman::~CConnman()
{ {
} }
size_t CConnman::GetAddressCount() const
{
return addrman.size();
}
void CConnman::SetServices(const CService &addr, ServiceFlags nServices)
{
addrman.SetServices(addr, nServices);
}
void CConnman::MarkAddressGood(const CAddress& addr)
{
addrman.Good(addr);
}
void CConnman::AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty)
{
addrman.Add(addr, addrFrom, nTimePenalty);
}
void CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
{
addrman.Add(vAddr, addrFrom, nTimePenalty);
}
std::vector<CAddress> CConnman::GetAddresses()
{
return addrman.GetAddr();
}
void RelayTransaction(const CTransaction& tx) void RelayTransaction(const CTransaction& tx)
{ {
CInv inv(MSG_TX, tx.GetHash()); CInv inv(MSG_TX, tx.GetHash());

89
src/net.h

@ -7,6 +7,7 @@
#define BITCOIN_NET_H #define BITCOIN_NET_H
#include "addrdb.h" #include "addrdb.h"
#include "addrman.h"
#include "amount.h" #include "amount.h"
#include "bloom.h" #include "bloom.h"
#include "compat.h" #include "compat.h"
@ -87,7 +88,6 @@ unsigned int SendBufferSize();
typedef int NodeId; typedef int NodeId;
void AddOneShot(const std::string& strDest); void AddOneShot(const std::string& strDest);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const CSubNet& subNet);
CNode* FindNode(const std::string& addrName); CNode* FindNode(const std::string& addrName);
@ -99,11 +99,44 @@ class CConnman
public: public:
CConnman(); CConnman();
~CConnman(); ~CConnman();
bool Start(boost::thread_group& threadGroup, std::string& strNodeError); bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError);
void Stop(); void Stop();
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
// Addrman functions
size_t GetAddressCount() const;
void SetServices(const CService &addr, ServiceFlags nServices);
void MarkAddressGood(const CAddress& addr);
void AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
std::vector<CAddress> GetAddresses();
void AddressCurrentlyConnected(const CService& addr);
// Denial-of-service detection/prevention
// The idea is to detect peers that are behaving
// badly and disconnect/ban them, but do it in a
// one-coding-mistake-won't-shatter-the-entire-network
// way.
// IMPORTANT: There should be nothing I can give a
// node that it will forward on that will make that
// node's peers drop it. If there is, an attacker
// can isolate a node and/or try to split the network.
// Dropping a node for sending stuff that is invalid
// now but might be valid in a later version is also
// dangerous, because it can cause a network split
// between nodes running old code and nodes running
// new code.
void Ban(const CNetAddr& netAddr, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
void Ban(const CSubNet& subNet, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
void ClearBanned(); // needed for unit testing
bool IsBanned(CNetAddr ip);
bool IsBanned(CSubNet subnet);
bool Unban(const CNetAddr &ip);
bool Unban(const CSubNet &ip);
void GetBanned(banmap_t &banmap);
void SetBanned(const banmap_t &banmap);
private: private:
struct ListenSocket { struct ListenSocket {
SOCKET socket; SOCKET socket;
@ -122,8 +155,22 @@ private:
CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure);
void DeleteNode(CNode* pnode); void DeleteNode(CNode* pnode);
//!check is the banlist has unwritten changes
bool BannedSetIsDirty();
//!set the "dirty" flag for the banlist
void SetBannedSetDirty(bool dirty=true);
//!clean unused entries (if bantime has expired)
void SweepBanned();
void DumpAddresses();
void DumpData();
void DumpBanlist();
std::vector<ListenSocket> vhListenSocket; std::vector<ListenSocket> vhListenSocket;
banmap_t setBanned;
CCriticalSection cs_setBanned;
bool setBannedIsDirty;
bool fAddressesInitialized;
CAddrMan addrman;
}; };
extern std::unique_ptr<CConnman> g_connman; extern std::unique_ptr<CConnman> g_connman;
void MapPort(bool fUseUPnP); void MapPort(bool fUseUPnP);
@ -195,7 +242,6 @@ extern ServiceFlags nLocalServices;
extern ServiceFlags nRelevantServices; extern ServiceFlags nRelevantServices;
extern bool fRelayTxes; extern bool fRelayTxes;
extern uint64_t nLocalHostNonce; extern uint64_t nLocalHostNonce;
extern CAddrMan addrman;
/** Maximum number of connections to simultaneously allow (aka connection slots) */ /** Maximum number of connections to simultaneously allow (aka connection slots) */
extern int nMaxConnections; extern int nMaxConnections;
@ -347,12 +393,6 @@ public:
const uint64_t nKeyedNetGroup; const uint64_t nKeyedNetGroup;
protected: protected:
// Denial-of-service detection/prevention
// Key is IP address, value is banned-until-time
static banmap_t setBanned;
static CCriticalSection cs_setBanned;
static bool setBannedIsDirty;
// Whitelisted ranges. Any node connecting from these is automatically // Whitelisted ranges. Any node connecting from these is automatically
// whitelisted (as well as those connecting to whitelisted binds). // whitelisted (as well as those connecting to whitelisted binds).
static std::vector<CSubNet> vWhitelistedRange; static std::vector<CSubNet> vWhitelistedRange;
@ -722,37 +762,6 @@ public:
void CloseSocketDisconnect(); void CloseSocketDisconnect();
// Denial-of-service detection/prevention
// The idea is to detect peers that are behaving
// badly and disconnect/ban them, but do it in a
// one-coding-mistake-won't-shatter-the-entire-network
// way.
// IMPORTANT: There should be nothing I can give a
// node that it will forward on that will make that
// node's peers drop it. If there is, an attacker
// can isolate a node and/or try to split the network.
// Dropping a node for sending stuff that is invalid
// now but might be valid in a later version is also
// dangerous, because it can cause a network split
// between nodes running old code and nodes running
// new code.
static void ClearBanned(); // needed for unit testing
static bool IsBanned(CNetAddr ip);
static bool IsBanned(CSubNet subnet);
static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
static bool Unban(const CNetAddr &ip);
static bool Unban(const CSubNet &ip);
static void GetBanned(banmap_t &banmap);
static void SetBanned(const banmap_t &banmap);
//!check is the banlist has unwritten changes
static bool BannedSetIsDirty();
//!set the "dirty" flag for the banlist
static void SetBannedSetDirty(bool dirty=true);
//!clean unused entries (if bantime has expired)
static void SweepBanned();
void copyStats(CNodeStats &stats); void copyStats(CNodeStats &stats);
static bool IsWhitelistedRange(const CNetAddr &ip); static bool IsWhitelistedRange(const CNetAddr &ip);

3
src/qt/bantablemodel.cpp

@ -48,7 +48,8 @@ public:
void refreshBanlist() void refreshBanlist()
{ {
banmap_t banMap; banmap_t banMap;
CNode::GetBanned(banMap); if(g_connman)
g_connman->GetBanned(banMap);
cachedBanlist.clear(); cachedBanlist.clear();
#if QT_VERSION >= 0x040700 #if QT_VERSION >= 0x040700

11
src/qt/rpcconsole.cpp

@ -887,13 +887,12 @@ void RPCConsole::disconnectSelectedNode()
void RPCConsole::banSelectedNode(int bantime) void RPCConsole::banSelectedNode(int bantime)
{ {
if (!clientModel) if (!clientModel || !g_connman)
return; return;
// Get currently selected peer address // Get currently selected peer address
QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString();
// Find possible nodes, ban it and clear the selected node // Find possible nodes, ban it and clear the selected node
if (FindNode(strNode.toStdString())) {
std::string nStr = strNode.toStdString(); std::string nStr = strNode.toStdString();
std::string addr; std::string addr;
int port = 0; int port = 0;
@ -902,12 +901,10 @@ void RPCConsole::banSelectedNode(int bantime)
CNetAddr resolved; CNetAddr resolved;
if(!LookupHost(addr.c_str(), resolved, false)) if(!LookupHost(addr.c_str(), resolved, false))
return; return;
CNode::Ban(resolved, BanReasonManuallyAdded, bantime); g_connman->Ban(resolved, BanReasonManuallyAdded, bantime);
clearSelectedNode(); clearSelectedNode();
clientModel->getBanTableModel()->refresh(); clientModel->getBanTableModel()->refresh();
} }
}
void RPCConsole::unbanSelectedNode() void RPCConsole::unbanSelectedNode()
{ {
@ -919,9 +916,9 @@ void RPCConsole::unbanSelectedNode()
CSubNet possibleSubnet; CSubNet possibleSubnet;
LookupSubNet(strNode.toStdString().c_str(), possibleSubnet); LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
if (possibleSubnet.IsValid()) if (possibleSubnet.IsValid() && g_connman)
{ {
CNode::Unban(possibleSubnet); g_connman->Unban(possibleSubnet);
clientModel->getBanTableModel()->refresh(); clientModel->getBanTableModel()->refresh();
} }
} }

17
src/rpc/net.cpp

@ -488,6 +488,8 @@ UniValue setban(const UniValue& params, bool fHelp)
+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
+ HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
); );
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
CSubNet subNet; CSubNet subNet;
CNetAddr netAddr; CNetAddr netAddr;
@ -509,7 +511,7 @@ UniValue setban(const UniValue& params, bool fHelp)
if (strCommand == "add") if (strCommand == "add")
{ {
if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr)) if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr))
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
int64_t banTime = 0; //use standard bantime if not specified int64_t banTime = 0; //use standard bantime if not specified
@ -520,11 +522,11 @@ UniValue setban(const UniValue& params, bool fHelp)
if (params.size() == 4 && params[3].isTrue()) if (params.size() == 4 && params[3].isTrue())
absolute = true; absolute = true;
isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
} }
else if(strCommand == "remove") else if(strCommand == "remove")
{ {
if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) ))
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
} }
return NullUniValue; return NullUniValue;
@ -541,8 +543,11 @@ UniValue listbanned(const UniValue& params, bool fHelp)
+ HelpExampleRpc("listbanned", "") + HelpExampleRpc("listbanned", "")
); );
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
banmap_t banMap; banmap_t banMap;
CNode::GetBanned(banMap); g_connman->GetBanned(banMap);
UniValue bannedAddresses(UniValue::VARR); UniValue bannedAddresses(UniValue::VARR);
for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
@ -570,8 +575,10 @@ UniValue clearbanned(const UniValue& params, bool fHelp)
+ HelpExampleCli("clearbanned", "") + HelpExampleCli("clearbanned", "")
+ HelpExampleRpc("clearbanned", "") + HelpExampleRpc("clearbanned", "")
); );
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
CNode::ClearBanned(); g_connman->ClearBanned();
return NullUniValue; return NullUniValue;
} }

28
src/test/DoS_tests.cpp

@ -44,15 +44,15 @@ BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_AUTO_TEST_CASE(DoS_banning)
{ {
CNode::ClearBanned(); connman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE); CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(INVALID_SOCKET, addr1, "", true); CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1);
dummyNode1.nVersion = 1; dummyNode1.nVersion = 1;
Misbehaving(dummyNode1.GetId(), 100); // Should get banned Misbehaving(dummyNode1.GetId(), 100); // Should get banned
SendMessages(&dummyNode1, *connman); SendMessages(&dummyNode1, *connman);
BOOST_CHECK(CNode::IsBanned(addr1)); BOOST_CHECK(connman->IsBanned(addr1));
BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
CAddress addr2(ip(0xa0b0c002), NODE_NONE); CAddress addr2(ip(0xa0b0c002), NODE_NONE);
CNode dummyNode2(INVALID_SOCKET, addr2, "", true); CNode dummyNode2(INVALID_SOCKET, addr2, "", true);
@ -60,16 +60,16 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
dummyNode2.nVersion = 1; dummyNode2.nVersion = 1;
Misbehaving(dummyNode2.GetId(), 50); Misbehaving(dummyNode2.GetId(), 50);
SendMessages(&dummyNode2, *connman); SendMessages(&dummyNode2, *connman);
BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet... BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
Misbehaving(dummyNode2.GetId(), 50); Misbehaving(dummyNode2.GetId(), 50);
SendMessages(&dummyNode2, *connman); SendMessages(&dummyNode2, *connman);
BOOST_CHECK(CNode::IsBanned(addr2)); BOOST_CHECK(connman->IsBanned(addr2));
} }
BOOST_AUTO_TEST_CASE(DoS_banscore) BOOST_AUTO_TEST_CASE(DoS_banscore)
{ {
CNode::ClearBanned(); connman->ClearBanned();
mapArgs["-banscore"] = "111"; // because 11 is my favorite number mapArgs["-banscore"] = "111"; // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001), NODE_NONE); CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(INVALID_SOCKET, addr1, "", true); CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
@ -77,19 +77,19 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
dummyNode1.nVersion = 1; dummyNode1.nVersion = 1;
Misbehaving(dummyNode1.GetId(), 100); Misbehaving(dummyNode1.GetId(), 100);
SendMessages(&dummyNode1, *connman); SendMessages(&dummyNode1, *connman);
BOOST_CHECK(!CNode::IsBanned(addr1)); BOOST_CHECK(!connman->IsBanned(addr1));
Misbehaving(dummyNode1.GetId(), 10); Misbehaving(dummyNode1.GetId(), 10);
SendMessages(&dummyNode1, *connman); SendMessages(&dummyNode1, *connman);
BOOST_CHECK(!CNode::IsBanned(addr1)); BOOST_CHECK(!connman->IsBanned(addr1));
Misbehaving(dummyNode1.GetId(), 1); Misbehaving(dummyNode1.GetId(), 1);
SendMessages(&dummyNode1, *connman); SendMessages(&dummyNode1, *connman);
BOOST_CHECK(CNode::IsBanned(addr1)); BOOST_CHECK(connman->IsBanned(addr1));
mapArgs.erase("-banscore"); mapArgs.erase("-banscore");
} }
BOOST_AUTO_TEST_CASE(DoS_bantime) BOOST_AUTO_TEST_CASE(DoS_bantime)
{ {
CNode::ClearBanned(); connman->ClearBanned();
int64_t nStartTime = GetTime(); int64_t nStartTime = GetTime();
SetMockTime(nStartTime); // Overrides future calls to GetTime() SetMockTime(nStartTime); // Overrides future calls to GetTime()
@ -100,13 +100,13 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
Misbehaving(dummyNode.GetId(), 100); Misbehaving(dummyNode.GetId(), 100);
SendMessages(&dummyNode, *connman); SendMessages(&dummyNode, *connman);
BOOST_CHECK(CNode::IsBanned(addr)); BOOST_CHECK(connman->IsBanned(addr));
SetMockTime(nStartTime+60*60); SetMockTime(nStartTime+60*60);
BOOST_CHECK(CNode::IsBanned(addr)); BOOST_CHECK(connman->IsBanned(addr));
SetMockTime(nStartTime+60*60*24+1); SetMockTime(nStartTime+60*60*24+1);
BOOST_CHECK(!CNode::IsBanned(addr)); BOOST_CHECK(!connman->IsBanned(addr));
} }
CTransaction RandomOrphan() CTransaction RandomOrphan()

Loading…
Cancel
Save