]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Implement a simple (braindead) mechansim to force DoT the specific auths: a fixed...
authorOtto <otto.moerbeek@open-xchange.com>
Wed, 9 Jun 2021 12:43:55 +0000 (14:43 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Fri, 18 Jun 2021 06:47:43 +0000 (08:47 +0200)
of names or suffixes of the special nameservers.

pdns/pdns_recursor.cc
pdns/recursordist/docs/settings.rst
pdns/recursordist/test-syncres_cc.cc
pdns/syncres.cc
pdns/syncres.hh
regression-tests.recursor-dnssec/test_SimpleForwardOverDoT.py

index 322005a5c7c7b82857812d8b40129d6d9d38b3dc..bf7a0d4dbaee63049bdddaaac19c240707e01703 100644 (file)
@@ -265,6 +265,7 @@ GlobalStateHolder<SuffixMatchNode> g_xdnssec;
 // Used in the Syncres to not throttle certain servers
 GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
 GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
+GlobalStateHolder<SuffixMatchNode> 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<string> 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");
index b63ec0871ed4f25fc7b92f81f87396c4421b5677..c32b659247d544fcb5a815238f8931a18c12bc29 100644 (file)
@@ -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``
index d593d5c62f818b8ac81729e0bd36c8400c971c20..7b62525be186c9618bdccb347f55d8bdd636401b 100644 (file)
@@ -13,6 +13,7 @@ GlobalStateHolder<LuaConfigItems> g_luaconfs;
 GlobalStateHolder<SuffixMatchNode> g_xdnssec;
 GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
 GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
+GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames;
 std::unique_ptr<MemRecursorCache> g_recCache{nullptr};
 std::unique_ptr<NegCache> g_negCache{nullptr};
 unsigned int g_numThreads = 1;
index dc1eb2894f514f67e0970e54c75dbe29b6ae299e..83f7576d30622d6297d78bd572ac56374fb17af1 100644 (file)
@@ -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<Netmask>& 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<Netmask>& 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<<qname<<": using DoT with "<< remoteIP.toStringWithPort() <<endl);
       s_dotoutqueries++;
       d_dotoutqueries++;
@@ -4103,6 +4103,11 @@ bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qn
   return false;
 }
 
+bool SyncRes::doDoTtoAuth(const DNSName& ns) const
+{
+  return g_DoTToAuthNames.getLocal()->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<ComboAddress> remoteIPs_t;
       remoteIPs_t remoteIPs;
-      remoteIPs_t::const_iterator remoteIP;
+      remoteIPs_t::iterator remoteIP;
       bool pierceDontQuery=false;
       bool sendRDQuery=false;
       boost::optional<Netmask> ednsmask;
@@ -4217,8 +4222,8 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
         else {
           bool hitPolicy{false};
           LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<tns->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<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.toString()<<"'"<<endl);
 
           if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
@@ -4249,16 +4254,25 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
           bool truncated = false;
           bool spoofed = false;
           bool gotAnswer = false;
-          bool forceTCP = SyncRes::s_dot_to_port_853 && remoteIP->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) {
index 0e820dc46942e800d5f8d496074bedfb9e8ef8f7..a67a0ab216eb7b502e9633b64c0ab9330ccea9da 100644 (file)
@@ -66,6 +66,7 @@
 extern GlobalStateHolder<SuffixMatchNode> g_xdnssec;
 extern GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
 extern GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
+extern GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames;
 
 class RecursorLua4;
 
@@ -829,9 +830,10 @@ private:
   typedef std::map<DNSName,vState> 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<DNSRecord>&ret,
                   unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state, StopAtDelegation* stopAtDelegation);
-  bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional<Netmask>& 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<Netmask>& 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<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const ComboAddress& remoteIP);
 
   int doResolve(const DNSName &qname, QType qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state);
index 768bbe68b558c548fd79222f148c8c58b6627794..ae44e0f0862e7e06e8c4715f08744a79f41325a9 100644 (file)
@@ -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
 
-