diff --git a/src/chainparams.h b/src/chainparams.h --- a/src/chainparams.h +++ b/src/chainparams.h @@ -85,7 +85,7 @@ /** Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } /** Return the list of hostnames to look up for DNS seeds */ - const std::vector &DNSSeeds() const { return vSeeds; } + const std::vector GetRandomizedDNSSeeds() const; const std::vector &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } diff --git a/src/chainparams.cpp b/src/chainparams.cpp --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,19 @@ nBits, nVersion, genesisReward); } +const std::vector CChainParams::GetRandomizedDNSSeeds() const { + FastRandomContext rng; + std::vector seeds; + if (gArgs.IsArgSet("-overridednsseed")) { + seeds = {gArgs.GetArg("-overridednsseed", "")}; + } else { + seeds = vSeeds; + } + + Shuffle(seeds.begin(), seeds.end(), rng); + return seeds; +} + /** * Main network */ diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -662,6 +662,10 @@ "Always query for peer addresses via DNS lookup (default: %d)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + argsman.AddArg("-overridednsseed", + "If set, only use the specified DNS seed when " + "querying for peer addresses via DNS lookup.", + ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg( "-listen", "Accept connections from outside (default: 1 if no -proxy or -connect)", diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -1732,8 +1732,8 @@ void CConnman::ThreadDNSAddressSeed() { FastRandomContext rng; - std::vector seeds = config->GetChainParams().DNSSeeds(); - Shuffle(seeds.begin(), seeds.end(), rng); + std::vector seeds = + config->GetChainParams().GetRandomizedDNSSeeds(); // Number of seeds left before testing if we have enough connections int seeds_right_now = 0; int found = 0; diff --git a/src/seeder/main.cpp b/src/seeder/main.cpp --- a/src/seeder/main.cpp +++ b/src/seeder/main.cpp @@ -148,6 +148,10 @@ ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-onion=", "Tor proxy IP/Port", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + argsman.AddArg("-overridednsseed", + "If set, only use the specified DNS seed when " + "querying for peer addresses via DNS lookup.", + ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-proxyipv4=", "IPV4 SOCKS5 proxy IP/Port", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-proxyipv6=", "IPV6 SOCKS5 proxy IP/Port", @@ -460,7 +464,7 @@ extern "C" void *ThreadSeeder(void *) { do { - for (const std::string &seed : Params().DNSSeeds()) { + for (const std::string &seed : Params().GetRandomizedDNSSeeds()) { std::vector ips; LookupHost(seed.c_str(), ips, MAX_HOSTS_PER_SEED, true); for (auto &ip : ips) { diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -194,6 +194,7 @@ script_standard_tests.cpp script_tests.cpp scriptnum_tests.cpp + seeds_tests.cpp serialize_tests.cpp settings_tests.cpp sigcache_tests.cpp diff --git a/src/test/seeds_tests.cpp b/src/test/seeds_tests.cpp new file mode 100644 --- /dev/null +++ b/src/test/seeds_tests.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2020 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#include + +BOOST_FIXTURE_TEST_SUITE(seeds_tests, TestingSetup) + +BOOST_AUTO_TEST_CASE(override_dns_seed) { + // No override should always provide some DNS seeds + const auto params = CreateChainParams(CBaseChainParams::MAIN); + BOOST_CHECK(params->GetRandomizedDNSSeeds().size() > 0); + + // Overriding should only return that DNS seed + gArgs.ForceSetArg("-overridednsseed", "localhost"); + BOOST_CHECK(params->GetRandomizedDNSSeeds() == + std::vector{{"localhost"}}); +} + +BOOST_AUTO_TEST_SUITE_END()