p2p: Don't query DNS seeds when both IPv4 and IPv6 are unreachable

This happens, for example, if the user specified -onlynet=onion or
-onlynet=i2p. DNS seeds only resolve to IPv4 / IPv6 addresses,
making their answers useless to us, since we don't want to make
connections to these.
If, within the DNS seed thread, we'd instead do fallback AddrFetch
connections to one of the clearnet addresses the DNS seed resolves to,
we might get usable addresses from other networks
if lucky, but would be violating our -onlynet user preference
in doing so.

Therefore, in this case it is better to rely on fixed seeds for networks we
want to connect to.

Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
This commit is contained in:
Martin Zumsande 2022-07-22 14:51:44 -04:00
parent 91f0a7fbb7
commit 385f5a4c3f
3 changed files with 20 additions and 2 deletions

View File

@ -719,6 +719,16 @@ void InitParameterInteraction(ArgsManager& args)
if (args.SoftSetBoolArg("-whitelistrelay", true)) if (args.SoftSetBoolArg("-whitelistrelay", true))
LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__); LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__);
} }
if (args.IsArgSet("-onlynet")) {
const auto onlynets = args.GetArgs("-onlynet");
bool clearnet_reachable = std::any_of(onlynets.begin(), onlynets.end(), [](const auto& net) {
const auto n = ParseNetwork(net);
return n == NET_IPV4 || n == NET_IPV6;
});
if (!clearnet_reachable && args.SoftSetBoolArg("-dnsseed", false)) {
LogPrintf("%s: parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n", __func__);
}
}
} }
/** /**
@ -1322,6 +1332,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// 2.1. -onlynet is not given or // 2.1. -onlynet is not given or
// 2.2. -onlynet=cjdns is given // 2.2. -onlynet=cjdns is given
// Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
// If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
// the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
if (args.GetBoolArg("-dnsseed") == true && !IsReachable(NET_IPV4) && !IsReachable(NET_IPV6)) {
return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
};
// Check for host lookup allowed before parsing any network related parameters // Check for host lookup allowed before parsing any network related parameters
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);

View File

@ -1630,7 +1630,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex); LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex);
if (m_addr_fetches.empty() && m_added_nodes.empty()) { if (m_addr_fetches.empty() && m_added_nodes.empty()) {
add_fixed_seeds_now = true; add_fixed_seeds_now = true;
LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n"); LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n");
} }
} }

View File

@ -186,11 +186,12 @@ class ConfArgsTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=[ with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat", "Loaded 0 addresses from peers.dat",
"DNS seeding disabled", "DNS seeding disabled",
"Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n", "Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n",
]): ]):
self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1']) self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1'])
assert time.time() - start < 60 assert time.time() - start < 60
self.stop_node(0) self.stop_node(0)
self.nodes[0].assert_start_raises_init_error(['-dnsseed=1', '-onlynet=i2p', '-i2psam=127.0.0.1:7656'], "Error: Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")
# No peers.dat exists and dns seeds are disabled. # No peers.dat exists and dns seeds are disabled.
# We expect the node will not add fixed seeds when explicitly disabled. # We expect the node will not add fixed seeds when explicitly disabled.