diff options
author | fanquake <fanquake@gmail.com> | 2019-09-23 12:41:32 +0800 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2019-09-23 12:53:50 +0800 |
commit | 3ce829888861a6dc6a29da669584ada961d965fa (patch) | |
tree | 4eb4b5a12182e78db6e186daf6bfef54cc091580 | |
parent | 13377b7a695c2fc774946cfd6a9aa01dd338e13c (diff) | |
parent | 6170ec5d3ac2bc206068b270e5722a7ecd3a8f26 (diff) |
Merge #15558: Don't query all DNS seeds at once
6170ec5d3ac2bc206068b270e5722a7ecd3a8f26 Do not query all DNS seed at once (Pieter Wuille)
Pull request description:
Before this PR, when we don't have enough connections after 11 seconds, we proceed to query all DNS seeds in a fixed order, loading responses from all of them.
Change this to to only query three randomly-selected DNS seed. If 11 seconds later we still don't have enough connections, try again with another one, and so on.
This reduces the amount of information DNS seeds can observe about the requesters by spreading the load over all of them.
ACKs for top commit:
Sjors:
ACK 6170ec5d3
sdaftuar:
ACK 6170ec5d3ac2bc206068b270e5722a7ecd3a8f26
jonasschnelli:
utACK 6170ec5d3ac2bc206068b270e5722a7ecd3a8f26 - I think the risk of a single seeder codebase is orthogonal to this PR. Such risks could also be interpreted differently (diversity could also increase the risk based on the threat model).
fanquake:
ACK 6170ec5d3ac2bc206068b270e5722a7ecd3a8f26 - Agree with the reasoning behind the change. Did some testing with and without `-forcednsseed` and/or a `peers.dat` and monitored the DNS activity.
Tree-SHA512: 33f6be5f924a85d312303ce272aa8f8d5e04cb616b4b492be98832e3ff37558d13d2b16ede68644ad399aff2bf5ff0ad33844e55eb40b7f8e3fddf9ae43add57
-rw-r--r-- | src/net.cpp | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/src/net.cpp b/src/net.cpp index 89f82aa3d2..63b7833822 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -50,6 +50,9 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" // Dump addresses to peers.dat every 15 minutes (900s) static constexpr int DUMP_PEERS_INTERVAL = 15 * 60; +/** Number of DNS seeds to query when the number of connections is low. */ +static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3; + // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. #define FEELER_SLEEP_WINDOW 1 @@ -1535,35 +1538,41 @@ void StopMapPort() void CConnman::ThreadDNSAddressSeed() { - // goal: only query DNS seeds if address need is acute - // Avoiding DNS seeds when we don't need them improves user privacy by - // creating fewer identifying DNS requests, reduces trust by giving seeds - // less influence on the network topology, and reduces traffic to the seeds. - if ((addrman.size() > 0) && - (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { - if (!interruptNet.sleep_for(std::chrono::seconds(11))) - return; + FastRandomContext rng; + std::vector<std::string> seeds = Params().DNSSeeds(); + Shuffle(seeds.begin(), seeds.end(), rng); + int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections + int found = 0; - LOCK(cs_vNodes); - int nRelevant = 0; - for (const CNode* pnode : vNodes) { - nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound; - } - if (nRelevant >= 2) { - LogPrintf("P2P peers available. Skipped DNS seeding.\n"); - return; - } + if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) { + // When -forcednsseed is provided, query all. + seeds_right_now = seeds.size(); } - const std::vector<std::string> &vSeeds = Params().DNSSeeds(); - int found = 0; + for (const std::string& seed : seeds) { + // goal: only query DNS seed if address need is acute + // Avoiding DNS seeds when we don't need them improves user privacy by + // creating fewer identifying DNS requests, reduces trust by giving seeds + // less influence on the network topology, and reduces traffic to the seeds. + if (addrman.size() > 0 && seeds_right_now == 0) { + if (!interruptNet.sleep_for(std::chrono::seconds(11))) return; - LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); + LOCK(cs_vNodes); + int nRelevant = 0; + for (const CNode* pnode : vNodes) { + nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound; + } + if (nRelevant >= 2) { + LogPrintf("P2P peers available. Skipped DNS seeding.\n"); + return; + } + seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE; + } - for (const std::string &seed : vSeeds) { if (interruptNet) { return; } + LogPrintf("Loading addresses from DNS seed %s\n", seed); if (HaveNameProxy()) { AddOneShot(seed); } else { @@ -1576,13 +1585,11 @@ void CConnman::ThreadDNSAddressSeed() continue; } unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed - if (LookupHost(host.c_str(), vIPs, nMaxIPs, true)) - { - for (const CNetAddr& ip : vIPs) - { + if (LookupHost(host.c_str(), vIPs, nMaxIPs, true)) { + for (const CNetAddr& ip : vIPs) { int nOneDay = 24*3600; CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits); - addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old + addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old vAdd.push_back(addr); found++; } @@ -1593,8 +1600,8 @@ void CConnman::ThreadDNSAddressSeed() AddOneShot(seed); } } + --seeds_right_now; } - LogPrintf("%d addresses found from DNS seeds\n", found); } |