Skip to content

Commit

Permalink
p2p: protect 1/4 inbound onion peers in SelectNodeToEvict()
Browse files Browse the repository at this point in the history
  • Loading branch information
jonatack committed Dec 25, 2020
1 parent 0d16768 commit c16ed37
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,12 @@ static bool CompareLocalHostTimeConnected(const NodeEvictionCandidate &a, const
return a.nTimeConnected > b.nTimeConnected;
}

static bool CompareOnionTimeConnected(const NodeEvictionCandidate& a, const NodeEvictionCandidate& b)
{
if (a.m_is_onion != b.m_is_onion) return b.m_is_onion;
return a.nTimeConnected > b.nTimeConnected;
}

static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
return a.nKeyedNetGroup < b.nKeyedNetGroup;
}
Expand Down Expand Up @@ -923,16 +929,25 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,

// Protect the half of the remaining nodes which have been connected the longest.
// This replicates the non-eviction implicit behavior, and precludes attacks that start later.
// Reserve half of these protected spots for localhost peers, even if
// Reserve half of these protected spots for onion and localhost peers, even if
// they're not longest-uptime overall. This helps protect tor peers, which
// tend to be otherwise disadvantaged under our eviction criteria.
size_t initial_size = vEvictionCandidates.size();
const size_t initial_size = vEvictionCandidates.size();
size_t total_protect_size = initial_size / 2;

// Pick out up to 1/4 peers that are localhost, sorted by longest uptime.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareLocalHostTimeConnected);
size_t local_erase_size = total_protect_size / 2;
vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.end() - local_erase_size, vEvictionCandidates.end(), [](NodeEvictionCandidate const &n) { return n.m_is_local; }), vEvictionCandidates.end());
// Pick out up to 1/4 peers that are connected via our tor onion service, sorted by longest uptime.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareOnionTimeConnected);
const size_t local_erase_size = total_protect_size / 2;
vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.end() - local_erase_size, vEvictionCandidates.end(), [](NodeEvictionCandidate const &n) { return n.m_is_onion; }), vEvictionCandidates.end());

// If no onion peers were removed, extend the same protection to localhost peers, as manually
// configured hidden services not using -bind will not be detected as inbound onion connections.
if (initial_size == vEvictionCandidates.size()) {
// Pick out up to 1/4 peers that are localhost, sorted by longest uptime.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareLocalHostTimeConnected);
vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.end() - local_erase_size, vEvictionCandidates.end(), [](NodeEvictionCandidate const &n) { return n.m_is_local; }), vEvictionCandidates.end());
}

// Calculate how many we removed, and update our total number of peers that
// we want to protect based on uptime accordingly.
total_protect_size -= initial_size - vEvictionCandidates.size();
Expand Down

0 comments on commit c16ed37

Please sign in to comment.