From b4ae1398940fa70383a65d1ad75e7ccbc5e030e5 Mon Sep 17 00:00:00 2001 From: Otto Date: Wed, 9 Jun 2021 14:43:55 +0200 Subject: [PATCH] Implement a simple (braindead) mechansim to force DoT the specific auths: a fixed list of names or suffixes of the special nameservers. --- pdns/pdns_recursor.cc | 12 +++++++ pdns/recursordist/docs/settings.rst | 13 ++++++++ pdns/recursordist/test-syncres_cc.cc | 1 + pdns/syncres.cc | 32 +++++++++++++------ pdns/syncres.hh | 4 ++- .../test_SimpleForwardOverDoT.py | 3 +- 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 322005a5c7..bf7a0d4dba 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -265,6 +265,7 @@ GlobalStateHolder g_xdnssec; // Used in the Syncres to not throttle certain servers GlobalStateHolder g_dontThrottleNames; GlobalStateHolder g_dontThrottleNetmasks; +GlobalStateHolder g_DoTToAuthNames; #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10" #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10" @@ -5047,6 +5048,16 @@ static int serviceMain(int argc, char*argv[]) g_xdnssec.setState(std::move(xdnssecNames)); } + { + SuffixMatchNode dotauthNames; + vector parts; + stringtok(parts, ::arg()["dot-to-auth-names"], " ,"); + for (const auto &p : parts) { + dotauthNames.add(DNSName(p)); + } + g_DoTToAuthNames.setState(std::move(dotauthNames)); + } + s_balancingFactor = ::arg().asDouble("distribution-load-factor"); if (s_balancingFactor != 0.0 && s_balancingFactor < 1.0) { s_balancingFactor = 0.0; @@ -5804,6 +5815,7 @@ int main(int argc, char **argv) ::arg().set("edns-padding-tag", "Packetcache tag associated to responses sent with EDNS padding, to prevent sending these to clients for which padding is not enabled.")="7830"; ::arg().set("dot-to-port-853", "Force DoT connection to target port 853 if DoT compiled in")="yes"; + ::arg().set("dot-to-auth-names", "Use DoT to authoritative servers with these names or suffixes")=""; ::arg().setCmd("help","Provide a helpful message"); ::arg().setCmd("version","Print version string"); diff --git a/pdns/recursordist/docs/settings.rst b/pdns/recursordist/docs/settings.rst index b63ec0871e..c32b659247 100644 --- a/pdns/recursordist/docs/settings.rst +++ b/pdns/recursordist/docs/settings.rst @@ -386,6 +386,19 @@ If `pdns-distributes-queries`_ is set, spawn this number of distributor threads handle incoming queries and distribute them to other threads based on a hash of the query, to maximize the cache hit ratio. +.. _settings-dot-to-auth-names: + +``dot-to-auth-names`` +------------------- +.. versionadded:: 4.6.0 + +- Comma separated list of domain-names or suffixes +- Default: (empty). + +Force DoT to the listed authoritative nameservers. For this to work, DoT support has to be compiled in. +Currently, the certificate is checked for validity, but the name in the certificate is not checked against +the name of the host. + .. _settings-dot-to-port-853: ``dot-to-port-853`` diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index d593d5c62f..7b62525be1 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -13,6 +13,7 @@ GlobalStateHolder g_luaconfs; GlobalStateHolder g_xdnssec; GlobalStateHolder g_dontThrottleNames; GlobalStateHolder g_dontThrottleNetmasks; +GlobalStateHolder g_DoTToAuthNames; std::unique_ptr g_recCache{nullptr}; std::unique_ptr g_negCache{nullptr}; unsigned int g_numThreads = 1; diff --git a/pdns/syncres.cc b/pdns/syncres.cc index dc1eb2894f..83f7576d30 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -3734,7 +3734,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co return done; } -bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool& truncated, bool& spoofed) +bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed) { bool chained = false; LWResult::Result resolveret = LWResult::Result::Success; @@ -3750,7 +3750,7 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, } if(doTCP) { - if (SyncRes::s_dot_to_port_853 && remoteIP.getPort() == 853) { + if (doDoT) { LOG(prefix<check(ns); +} + /** returns: * -1 in case of no results * rcode otherwise @@ -4173,7 +4178,7 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con typedef vector remoteIPs_t; remoteIPs_t remoteIPs; - remoteIPs_t::const_iterator remoteIP; + remoteIPs_t::iterator remoteIP; bool pierceDontQuery=false; bool sendRDQuery=false; boost::optional ednsmask; @@ -4217,8 +4222,8 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con else { bool hitPolicy{false}; LOG(prefix<first<<" to: "); - for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) { - if(remoteIP != remoteIPs.cbegin()) { + for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) { + if(remoteIP != remoteIPs.begin()) { LOG(", "); } LOG(remoteIP->toString()); @@ -4239,7 +4244,7 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con } } - for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) { + for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) { LOG(prefix<toStringWithPort() <<", asking '"<getPort() == 853; + bool doDoT = false; + + if (doDoTtoAuth(tns->first)) { + remoteIP->setPort(853); + doDoT = true; + } + if (SyncRes::s_dot_to_port_853 && remoteIP->getPort() == 853) { + doDoT = true; + } + bool forceTCP = doDoT; if (!forceTCP) { gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery, wasForwarded, - tns->first, *remoteIP, false, truncated, spoofed); + tns->first, *remoteIP, false, false, truncated, spoofed); } if (forceTCP || (spoofed || (gotAnswer && truncated))) { /* retry, over TCP this time */ gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery, wasForwarded, - tns->first, *remoteIP, true, truncated, spoofed); + tns->first, *remoteIP, true, doDoT, truncated, spoofed); } if (!gotAnswer) { diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 0e820dc469..a67a0ab216 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -66,6 +66,7 @@ extern GlobalStateHolder g_xdnssec; extern GlobalStateHolder g_dontThrottleNames; extern GlobalStateHolder g_dontThrottleNetmasks; +extern GlobalStateHolder g_DoTToAuthNames; class RecursorLua4; @@ -829,9 +830,10 @@ private: typedef std::map zonesStates_t; enum StopAtDelegation { DontStop, Stop, Stopped }; + bool doDoTtoAuth(const DNSName& ns) const; int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, QType qtype, vector&ret, unsigned int depth, set&beenthere, vState& state, StopAtDelegation* stopAtDelegation); - bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool& truncated, bool& spoofed); + bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed); bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType qtype, DNSName& auth, bool wasForwarded, const boost::optional ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const ComboAddress& remoteIP); int doResolve(const DNSName &qname, QType qtype, vector&ret, unsigned int depth, set& beenthere, vState& state); diff --git a/regression-tests.recursor-dnssec/test_SimpleForwardOverDoT.py b/regression-tests.recursor-dnssec/test_SimpleForwardOverDoT.py index 768bbe68b5..ae44e0f086 100644 --- a/regression-tests.recursor-dnssec/test_SimpleForwardOverDoT.py +++ b/regression-tests.recursor-dnssec/test_SimpleForwardOverDoT.py @@ -5,7 +5,7 @@ from recursortests import RecursorTest class testSimpleForwardOverDoT(RecursorTest): """ - This forwarding to a DoT srever in avery basic way and is dependent on Quad9 working + This is forwarding to a DoT server in a very basic way and is dependent on Quad9 working """ _confdir = 'SimpleForwardOverDoT' @@ -48,4 +48,3 @@ forward-zones-recurse=.=9.9.9.9:853 print(e.output) raise - -- 2.47.2