From: Otto Moerbeek Date: Fri, 22 Sep 2023 07:55:14 +0000 (+0200) Subject: Resolve NS names without QName Minimization. X-Git-Tag: rec-5.0.0-alpha2~43^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f31a4248bc7ef0267d2abad0c6a3ad6e99d61075;p=thirdparty%2Fpdns.git Resolve NS names without QName Minimization. The assumption being that using Qname Minimization for infra queries does not enhance privacy, but increases query load. Also determine max-qperq bound dynamically --- diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 09bf5acf8d..d46be55014 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -1644,6 +1644,7 @@ static int initSyncRes(Logr::log_t log) SyncRes::s_nonresolvingnsmaxfails = ::arg().asNum("non-resolving-ns-max-fails"); SyncRes::s_nonresolvingnsthrottletime = ::arg().asNum("non-resolving-ns-throttle-time"); SyncRes::s_serverID = ::arg()["server-id"]; + // This bound is dynamically adjusted in SyncRes, depending on qname minimization being active SyncRes::s_maxqperq = ::arg().asNum("max-qperq"); SyncRes::s_maxnsperresolve = ::arg().asNum("max-ns-per-resolve"); SyncRes::s_maxnsaddressqperq = ::arg().asNum("max-ns-address-qperq"); @@ -1686,12 +1687,6 @@ static int initSyncRes(Logr::log_t log) SyncRes::s_qnameminimization = ::arg().mustDo("qname-minimization"); - if (SyncRes::s_qnameminimization) { - // With an empty cache, a rev ipv6 query with dnssec enabled takes - // almost 100 queries. Default maxqperq is 60. - SyncRes::s_maxqperq = std::max(SyncRes::s_maxqperq, static_cast(100)); - } - SyncRes::s_hardenNXD = SyncRes::HardenNXD::DNSSEC; string value = ::arg()["nothing-below-nxdomain"]; if (value == "yes") { diff --git a/pdns/recursordist/syncres.cc b/pdns/recursordist/syncres.cc index 2a5b46ae4e..780264ed90 100644 --- a/pdns/recursordist/syncres.cc +++ b/pdns/recursordist/syncres.cc @@ -2107,7 +2107,7 @@ vector SyncRes::getAddrs(const DNSName& qname, unsigned int depth, Context newContext1; cset.clear(); // Go out to get A's - if (s_doIPv4 && doResolve(qname, QType::A, cset, depth + 1, beenthere, newContext1) == 0) { // this consults cache, OR goes out + if (s_doIPv4 && doResolveNoQNameMinimization(qname, QType::A, cset, depth + 1, beenthere, newContext1) == 0) { // this consults cache, OR goes out for (auto const& i : cset) { if (i.d_type == QType::A) { if (auto rec = getRR(i)) { @@ -2120,7 +2120,7 @@ vector SyncRes::getAddrs(const DNSName& qname, unsigned int depth, if (ret.empty()) { // We only go out immediately to find IPv6 records if we did not find any IPv4 ones. Context newContext2; - if (doResolve(qname, QType::AAAA, cset, depth + 1, beenthere, newContext2) == 0) { // this consults cache, OR goes out + if (doResolveNoQNameMinimization(qname, QType::AAAA, cset, depth + 1, beenthere, newContext2) == 0) { // this consults cache, OR goes out for (const auto& i : cset) { if (i.d_type == QType::AAAA) { if (auto rec = getRR(i)) { @@ -3420,8 +3420,17 @@ vector SyncRes::retrieveAddressesForNS(const std::string& prefix, void SyncRes::checkMaxQperQ(const DNSName& qname) const { - if (d_outqueries + d_throttledqueries > s_maxqperq) { - throw ImmediateServFailException("more than " + std::to_string(s_maxqperq) + " (max-qperq) queries sent or throttled while resolving " + qname.toLogString()); + auto bound = s_maxqperq; + if (d_qNameMinimization) { + // With an empty cache, a rev ipv6 query with dnssec enabled takes + // almost 100 queries. Default maxqperq is 60 + // Note: This no longer seems to be true. The examples taken from #8646 take now way less + // queries. The main reason seems to be a much better zone cut determination. + bound = std::max(100U, bound); + } + + if (d_outqueries + d_throttledqueries > bound) { + throw ImmediateServFailException("more than " + std::to_string(bound) + " (adjusted max-qperq) queries sent or throttled while resolving " + qname.toLogString()); } } diff --git a/pdns/recursordist/test-syncres_cc5.cc b/pdns/recursordist/test-syncres_cc5.cc index bb893939f1..367a68a6ce 100644 --- a/pdns/recursordist/test-syncres_cc5.cc +++ b/pdns/recursordist/test-syncres_cc5.cc @@ -1969,8 +1969,11 @@ BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm) DNSName auth(domain); DNSName com("com."); DNSName net("net."); + DNSName nsone("nsone.net."); + DNSName hero("herokuapp.com."); + DNSName p03nsone("dns1.p03.nsone.net."); - //cerr << ip.toString() << ": " << domain << '|' << QType(type).getName() << endl; + // cerr << ip.toString() << ": " << domain << '|' << QType(type).toString() << endl; if (type == QType::DS || type == QType::DNSKEY) { return genericDSAndDNSKEYHandler(res, domain, auth, type, keys); } @@ -1990,6 +1993,13 @@ BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm) addRRSIG(keys, res->d_records, g_rootdnsname, 300); addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); } + else if (domain == p03nsone && type == QType::A) { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, nsone, QType::NS, "dns1.p01.nsone.net.", DNSResourceRecord::AUTHORITY, 3600); + addNSECRecordToLW(nsone, DNSName("zzz.nsone.net."), {QType::NS, QType::SOA, QType::RRSIG, QType::DNSKEY}, 600, res->d_records); + addRRSIG(keys, res->d_records, net, 300); + addRecordToLW(res, "dns1.p01.nsone.net", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); + } else { BOOST_ASSERT(0); } @@ -1997,8 +2007,6 @@ BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm) } else if (ip == ComboAddress("192.0.2.1:53")) { - DNSName hero("herokuapp.com."); - DNSName nsone("nsone.net."); if (domain == hero && type == QType::NS) { setLWResult(res, 0, false, false, true); addRecordToLW(res, hero, QType::NS, "dns1.p03.nsone.net.", DNSResourceRecord::AUTHORITY, 3600); @@ -2018,11 +2026,9 @@ BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm) return LWResult::Result::Success; } else if (ip == ComboAddress("192.0.2.2:53")) { - DNSName hero("herokuapp.com."); DNSName p01("p01.nsone.net."); DNSName p03("p03.nsone.net."); DNSName p01nsone("dns1.p01.nsone.net."); - DNSName p03nsone("dns1.p03.nsone.net."); if (domain == hero && type == QType::NS) { setLWResult(res, 0, true, false, true); addRecordToLW(res, hero, QType::NS, "dns1.p03.nsone.net.", DNSResourceRecord::ANSWER, 3600); @@ -2058,7 +2064,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm) BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure); BOOST_REQUIRE_EQUAL(ret.size(), 2U); - BOOST_CHECK_EQUAL(queriesCount, 10U); + BOOST_CHECK_EQUAL(queriesCount, 8U); ret.clear(); res = sr->beginResolve(DNSName("dns1.p03.nsone.net."), QType(QType::A), QClass::IN, ret);