mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-02 20:05:45 +02:00
Allow connections from misbehavior banned peers.
This allows incoming connections from peers which are only banned due to an automatic misbehavior ban if doing so won't fill inbound. These peers are preferred for eviction when inbound fills, but may still be kept if they fall into the protected classes. This eviction preference lasts the entire life of the connection even if the ban expires. If they misbehave again they'll still get disconnected. The main purpose of banning on misbehavior is to prevent our connections from being wasted on unhelpful peers such as ones running incompatible consensus rules. For inbound peers this can be better accomplished with eviction preferences. A secondary purpose was to reduce resource waste from repeated abuse but virtually any attacker can get a nearly unlimited supply of addresses, so disconnection is about the best we can do.
This commit is contained in:
19
src/net.cpp
19
src/net.cpp
@@ -764,6 +764,7 @@ struct NodeEvictionCandidate
|
||||
bool fBloomFilter;
|
||||
CAddress addr;
|
||||
uint64_t nKeyedNetGroup;
|
||||
bool prefer_evict;
|
||||
};
|
||||
|
||||
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
|
||||
@@ -832,7 +833,8 @@ bool CConnman::AttemptToEvictConnection()
|
||||
NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
|
||||
node->nLastBlockTime, node->nLastTXTime,
|
||||
HasAllDesirableServiceFlags(node->nServices),
|
||||
node->fRelayTxes, node->pfilter != nullptr, node->addr, node->nKeyedNetGroup};
|
||||
node->fRelayTxes, node->pfilter != nullptr, node->addr, node->nKeyedNetGroup,
|
||||
node->m_prefer_evict};
|
||||
vEvictionCandidates.push_back(candidate);
|
||||
}
|
||||
}
|
||||
@@ -857,6 +859,14 @@ bool CConnman::AttemptToEvictConnection()
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
// If any remaining peers are preferred for eviction consider only them.
|
||||
// This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
|
||||
// then we probably don't want to evict it no matter what.
|
||||
if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](NodeEvictionCandidate const &n){return n.prefer_evict;})) {
|
||||
vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
|
||||
[](NodeEvictionCandidate const &n){return !n.prefer_evict;}),vEvictionCandidates.end());
|
||||
}
|
||||
|
||||
// Identify the network group with the most connections and youngest member.
|
||||
// (vEvictionCandidates is already sorted by reverse connect time)
|
||||
uint64_t naMostConnections;
|
||||
@@ -937,7 +947,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
// on all platforms. Set it again here just to be sure.
|
||||
SetSocketNoDelay(hSocket);
|
||||
|
||||
if (m_banman && m_banman->IsBanned(addr) && !whitelisted)
|
||||
int bannedlevel = m_banman ? m_banman->IsBannedLevel(addr) : 0;
|
||||
|
||||
// Don't accept connections from banned peers, but if our inbound slots aren't almost full, accept
|
||||
// if the only banning reason was an automatic misbehavior ban.
|
||||
if (!whitelisted && bannedlevel > ((nInbound + 1 < nMaxInbound) ? 1 : 0))
|
||||
{
|
||||
LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
|
||||
CloseSocket(hSocket);
|
||||
@@ -961,6 +975,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true);
|
||||
pnode->AddRef();
|
||||
pnode->fWhitelisted = whitelisted;
|
||||
pnode->m_prefer_evict = bannedlevel > 0;
|
||||
m_msgproc->InitializeNode(pnode);
|
||||
|
||||
LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
|
||||
|
||||
Reference in New Issue
Block a user