aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp32
1 files changed, 25 insertions, 7 deletions
diff --git a/src/net.cpp b/src/net.cpp
index ccc430f5c2..6642ef6515 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -877,6 +877,14 @@ public:
}
};
+/** Try to find a connection to evict when the node is full.
+ * Extreme care must be taken to avoid opening the node to attacker
+ * triggered network partitioning.
+ * The strategy used here is to protect a small number of peers
+ * for each of several distinct characteristics which are difficult
+ * to forge. In order to partition a node the attacker must be
+ * simultaneously better at all of them than honest peers.
+ */
static bool AttemptToEvictConnection(bool fPreferNewConnection) {
std::vector<CNodeRef> vEvictionCandidates;
{
@@ -905,7 +913,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
if (vEvictionCandidates.empty()) return false;
- // Protect the 8 nodes with the best ping times.
+ // Protect the 8 nodes with the lowest minimum ping time.
// An attacker cannot manipulate this metric without physically moving nodes closer to the target.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime);
vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
@@ -913,7 +921,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
if (vEvictionCandidates.empty()) return false;
// Protect the half of the remaining nodes which have been connected the longest.
- // This replicates the existing implicit behavior.
+ // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast<int>(vEvictionCandidates.size() / 2), vEvictionCandidates.end());
@@ -941,6 +949,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
vEvictionCandidates = mapAddrCounts[naMostConnections];
// Do not disconnect peers if there is only one unprotected connection from their network group.
+ // This step excessively favors netgroup diversity, and should be removed once more protective criteria are established.
if (vEvictionCandidates.size() <= 1)
// unless we prefer the new connection (for whitelisted peers)
if (!fPreferNewConnection)
@@ -1443,7 +1452,7 @@ void ThreadDNSAddressSeed()
} else {
vector<CNetAddr> vIPs;
vector<CAddress> vAdd;
- if (LookupHost(seed.host.c_str(), vIPs))
+ if (LookupHost(seed.host.c_str(), vIPs, 0, true))
{
BOOST_FOREACH(const CNetAddr& ip, vIPs)
{
@@ -1454,7 +1463,15 @@ void ThreadDNSAddressSeed()
found++;
}
}
- addrman.Add(vAdd, CNetAddr(seed.name, true));
+ // TODO: The seed name resolve may fail, yielding an IP of [::], which results in
+ // addrman assigning the same source to results from different seeds.
+ // This should switch to a hard-coded stable dummy IP for each seed name, so that the
+ // resolve is not required at all.
+ if (!vIPs.empty()) {
+ CService seedSource;
+ Lookup(seed.name.c_str(), seedSource, 0, true);
+ addrman.Add(vAdd, seedSource);
+ }
}
}
@@ -1884,7 +1901,7 @@ void static Discover(boost::thread_group& threadGroup)
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
{
vector<CNetAddr> vaddr;
- if (LookupHost(pszHostName, vaddr))
+ if (LookupHost(pszHostName, vaddr, 0, true))
{
BOOST_FOREACH (const CNetAddr &addr, vaddr)
{
@@ -2614,9 +2631,10 @@ void DumpBanlist()
CBanDB bandb;
banmap_t banmap;
+ CNode::SetBannedSetDirty(false);
CNode::GetBanned(banmap);
- if (bandb.Write(banmap))
- CNode::SetBannedSetDirty(false);
+ if (!bandb.Write(banmap))
+ CNode::SetBannedSetDirty(true);
LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart);