From: Otto Moerbeek Date: Wed, 9 Mar 2022 13:37:16 +0000 (+0100) Subject: Initial code to Probe nameservers for DoT. X-Git-Tag: rec-4.7.0-beta1^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=78deeddaeca65232b2ad7cec9653ea8531792d1e;p=thirdparty%2Fpdns.git Initial code to Probe nameservers for DoT. The ratelmiting code sure need so extra attention. Missing: pruning, stats, tests, docs. --- diff --git a/pdns/recursordist/docs/manpages/rec_control.1.rst b/pdns/recursordist/docs/manpages/rec_control.1.rst index 38f826a63e..0b2c222150 100644 --- a/pdns/recursordist/docs/manpages/rec_control.1.rst +++ b/pdns/recursordist/docs/manpages/rec_control.1.rst @@ -92,6 +92,9 @@ dump-cache *FILENAME* also dumped to the same file. The per-thread positive and negative cache dumps are separated with an appropriate comment. +dump-dot-probe-map *FILENAME* + Dump the contents of the DoT probe map to the *FILENAME* mentioned. + dump-edns *FILENAME* Dumps the EDNS status to the filename mentioned. This file should not exist already, PowerDNS will refuse to overwrite it. While dumping, the recursor diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 6fe927e428..5e1a377bb7 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -1319,6 +1319,7 @@ static int serviceMain(int argc, char* argv[]) SyncRes::s_dot_to_port_853 = ::arg().mustDo("dot-to-port-853"); SyncRes::s_event_trace_enabled = ::arg().asNum("event-trace-enabled"); SyncRes::s_save_parent_ns_set = ::arg().mustDo("save-parent-ns-set"); + SyncRes::s_max_busy_dot_probes = ::arg().asNum("max-busy-dot-probes"); if (SyncRes::s_tcp_fast_open_connect) { checkFastOpenSysctl(true); @@ -2521,6 +2522,7 @@ int main(int argc, char** argv) ::arg().set("tcp-out-max-idle-per-thread", "Maximum number of idle TCP/DoT connections per thread") = "100"; ::arg().setSwitch("structured-logging", "Prefer structured logging") = "yes"; ::arg().setSwitch("save-parent-ns-set", "Save parent NS set to be used if child NS set fails") = "yes"; + ::arg().set("max-busy-dot-probes", "Maximum number of concurrent DoT probes") = "0"; ::arg().setCmd("help", "Provide a helpful message"); ::arg().setCmd("version", "Print version string"); diff --git a/pdns/recursordist/taskqueue.hh b/pdns/recursordist/taskqueue.hh index a57a81fe6b..5c55f4ae0e 100644 --- a/pdns/recursordist/taskqueue.hh +++ b/pdns/recursordist/taskqueue.hh @@ -27,7 +27,7 @@ union ComboAddress; namespace boost { - size_t hash_value(const ComboAddress&); +size_t hash_value(const ComboAddress&); } #include @@ -41,7 +41,6 @@ namespace boost #include "iputils.hh" #include "qtype.hh" - namespace pdns { using namespace ::boost::multi_index; @@ -129,4 +128,3 @@ private: }; } - diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 935c129b31..9e5e65c2b6 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -290,7 +290,7 @@ struct DoTStatus { enum Status : uint8_t { Unknown, Busy, Bad, Good }; DNSName d_auth; - time_t d_last; + time_t d_ttd; Status d_status{Unknown}; std::string toString() const { @@ -300,15 +300,16 @@ struct DoTStatus } }; +// FIXME: Pruning NYI class DotMap: public map { public: uint64_t d_numBusy{0}; }; -LockGuarded s_dotMap; +static LockGuarded s_dotMap; -const time_t dotFailWait = 24 * 3600; -const time_t dotSuccessWait = 3 * 24 * 3600; +static const time_t dotFailWait = 24 * 3600; +static const time_t dotSuccessWait = 3 * 24 * 3600; unsigned int SyncRes::s_maxnegttl; unsigned int SyncRes::s_maxbogusttl; @@ -362,6 +363,7 @@ bool SyncRes::s_tcp_fast_open_connect; bool SyncRes::s_dot_to_port_853; int SyncRes::s_event_trace_enabled; bool SyncRes::s_save_parent_ns_set; +unsigned int SyncRes::s_max_busy_dot_probes; #define LOG(x) if(d_lm == Log) { g_log <emplace(address, DoTStatus{auth, now}).first; - if (it->second.d_status == DoTStatus::Busy) { - cerr << "Already probing DoT for " << address.toString() << endl << endl; + if (lock->d_numBusy >= SyncRes::s_max_busy_dot_probes) { return; } - if (it->second.d_status == DoTStatus::Bad && it->second.d_last + dotFailWait > now) { - cerr << "Bad DoT for " << address.toString()<< endl << endl; + auto it = lock->emplace(address, DoTStatus{auth, now + dotFailWait}).first; + if (it->second.d_status == DoTStatus::Busy) { return; } - if (it->second.d_status == DoTStatus::Good && it->second.d_last + dotSuccessWait > now) { - cerr << "Good DoT for " << address.toString() << endl << endl; - return; + if (it->second.d_ttd > now) { + if (it->second.d_status == DoTStatus::Bad) { + return; + } + if (it->second.d_status == DoTStatus::Good) { + return; + } } - it->second.d_last = now; + it->second.d_ttd = now + dotFailWait; bool pushed = pushTryDoTTask(auth, QType::SOA, address, std::numeric_limits::max()); if (pushed) { - cerr << "Probing DoT for " << address.toString() << endl << endl; it->second.d_status = DoTStatus::Busy; ++lock->d_numBusy; - } else { - cerr << "NOT Probing DoT for " << address.toString() << endl << endl; } } @@ -4731,16 +4736,12 @@ static bool shouldDoDoT(ComboAddress address, time_t now) { address.setPort(853); auto lock = s_dotMap.lock(); - if (lock->d_numBusy > 1) { - cerr << "Busy DoT for " << address.toString() << endl << endl; - return false; - } auto it = lock->find(address); if (it == lock->end()) { + // Pruned... return false; } - if (it->second.d_status == DoTStatus::Good && it->second.d_last + dotSuccessWait > now) { - cerr << "Doing DoT for " << address.toString() << endl << endl; + if (it->second.d_status == DoTStatus::Good && it->second.d_ttd > now) { return true; } return false; @@ -4757,12 +4758,14 @@ bool SyncRes::tryDoT(const DNSName& qname, const QType qtype, const DNSName& aut ok = ok && lwr.d_rcode == RCode::NoError && lwr.d_records.size() > 0; auto lock = s_dotMap.lock(); - --lock->d_numBusy; auto it = lock->find(address); + // If an entry was removed by pruning, we do not adjust d_numBusy; it's the job of the pruning code to do that if (it != lock->end()) { - cerr << "DoT for " << address.toString() << ": " << ok << endl << endl; it->second.d_status = ok ? DoTStatus::Good : DoTStatus::Bad; + it->second.d_ttd = now + (ok ? dotSuccessWait : dotFailWait); + --lock->d_numBusy; } + return ok; } diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 98ca150256..2823f983c3 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -598,6 +598,7 @@ public: static int s_tcp_fast_open; static bool s_tcp_fast_open_connect; static bool s_dot_to_port_853; + static unsigned int s_max_busy_dot_probes; static const int event_trace_to_pb = 1; static const int event_trace_to_log = 2;