From 60495d2c92225c56a3a4d0408cf55b71786ae504 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Tue, 6 Sep 2022 09:50:52 +0200 Subject: [PATCH] For zones having many NS records, we are not interested in all so take a sample. (cherry picked from commit a49b0b40a0c1c1af9531b99e9266a8c2aa89cd68) --- pdns/pdns_recursor.cc | 2 ++ pdns/recursordist/docs/settings.rst | 13 +++++++++++++ pdns/syncres.cc | 7 +++++++ pdns/syncres.hh | 1 + 4 files changed, 23 insertions(+) diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 88cba06c0e..c0a62d2f2b 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -5188,6 +5188,7 @@ static int serviceMain(int argc, char*argv[]) SyncRes::s_nonresolvingnsthrottletime=::arg().asNum("non-resolving-ns-throttle-time"); SyncRes::s_serverID=::arg()["server-id"]; 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"); SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec"); SyncRes::s_maxdepth=::arg().asNum("max-recursion-depth"); @@ -6130,6 +6131,7 @@ int main(int argc, char **argv) ::arg().set("edns-outgoing-bufsize", "Outgoing EDNS buffer size")="1232"; ::arg().set("minimum-ttl-override", "The minimum TTL")="1"; ::arg().set("max-qperq", "Maximum outgoing queries per query")="60"; + ::arg().set("max-ns-per-resolve", "Maximum number of NS records to consider to resolve a name, 0 is no limit") = "13"; ::arg().set("max-ns-address-qperq", "Maximum outgoing NS address queries per query")="10"; ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="7000"; ::arg().set("max-recursion-depth", "Maximum number of internal recursion calls per query, 0 for unlimited")="40"; diff --git a/pdns/recursordist/docs/settings.rst b/pdns/recursordist/docs/settings.rst index 0aa80cfda3..0e1857e74c 100644 --- a/pdns/recursordist/docs/settings.rst +++ b/pdns/recursordist/docs/settings.rst @@ -1202,6 +1202,19 @@ it by the number of NS records found above the `max-ns-address-qperq`_ value. The limit wil not be reduced to a number lower than 5. +.. _setting-max-ns-per-resolve: + +``max-ns-per-resolve`` +---------------------- +.. versionadded:: 4.8.0 + +- Integer +- Default: 13 + +The maximum number of NS records that will be considered to select a nameserver to contact to resolve a name. +If a zone has more than `max-ns-per-resolve`_ NS records, a random sample of this size will be used. +If `max-ns-per-resolve`_ is zero, no limit applies. + .. _setting-max-negative-ttl: ``max-negative-ttl`` diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 372b6999b7..f7cdfbf160 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -53,6 +53,7 @@ unsigned int SyncRes::s_maxnegttl; unsigned int SyncRes::s_maxbogusttl; unsigned int SyncRes::s_maxcachettl; unsigned int SyncRes::s_maxqperq; +unsigned int SyncRes::s_maxnsperresolve; unsigned int SyncRes::s_maxnsaddressqperq; unsigned int SyncRes::s_maxtotusec; unsigned int SyncRes::s_maxdepth; @@ -1223,6 +1224,12 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType qtype, vector *flawedNSSet = false; if(g_recCache->get(d_now.tv_sec, subdomain, QType::NS, false, &ns, d_cacheRemote, false, d_routingTag) > 0) { + if (s_maxnsperresolve > 0 && ns.size() > s_maxnsperresolve) { + vector selected; + selected.reserve(s_maxnsperresolve); + std::sample(ns.cbegin(), ns.cend(), std::back_inserter(selected), s_maxnsperresolve, pdns::dns_random_engine()); + ns = selected; + } bestns.reserve(ns.size()); for(auto k=ns.cbegin();k!=ns.cend(); ++k) { diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 364f93aee6..e34614f12a 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -757,6 +757,7 @@ public: static unsigned int s_minimumTTL; static unsigned int s_minimumECSTTL; static unsigned int s_maxqperq; + static unsigned int s_maxnsperresolve; static unsigned int s_maxnsaddressqperq; static unsigned int s_maxtotusec; static unsigned int s_maxdepth; -- 2.47.2