]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
implement Marek Vavrusa's suggestion that dnsdist could be used for 'split horizon...
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 27 Feb 2015 20:44:12 +0000 (21:44 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 27 Feb 2015 20:44:12 +0000 (21:44 +0100)
pdns/README-dnsdist.md
pdns/dnsdist.cc
pdns/dnsdistconf.lua

index 4e5c47aca0c8500b3ffe94e3f6a2ba62ae4dd01b..1da9dbe555e8a321d4d4ee380dfa471ceb777415 100644 (file)
@@ -156,7 +156,7 @@ example:
 ```
 counter=0
 servers=getServers()
-function luaroundrobin(remote, qname, qtype) 
+function luaroundrobin(remote, qname, qtype, dh
         counter=counter+1
         return servers[1+(counter % #servers)]
 end
@@ -167,6 +167,27 @@ setServerPolicy(luaroundrobin)
 Incidentally, this is similar to setting: `setServerPolicy(roundrobin)`
 which uses the C++ based roundrobin policy.
 
+To implement a split horizon, try:
+
+```
+authServer=newServer2{address="2001:888:2000:1d::2", order=12}
+-- order=12 is the current hack to make sure this server does 
+-- generally get used, will be replaced by dedicated pools later
+
+function splitSetup(remote, qname, qtype, dh)
+        if(dh:getRD() == false)
+        then
+               return authServer
+        else
+               return firstAvailable(remote, qname, qtype, dh)
+        end
+end
+```
+
+This will forward queries that don't want recursion to a specific
+server, and will apply the default load balancing policy to all
+other queries.
+
 Running it for real
 -------------------
 First run on the command line, and generate a key:
index f5625046ef822a20ad4babd38a5402a0919d2af9..547be2ec9f4f94889fd39e33d45512313d53d48f 100644 (file)
@@ -44,6 +44,7 @@
 
 /* Known sins:
    We replace g_ACL w/o locking, might crash
+     g_policy too probably
    No centralized statistics
    We neglect to do recvfromto() on 0.0.0.0
    Receiver is currently singlethreaded (not that bad actually)
@@ -292,19 +293,9 @@ struct ClientState
 std::mutex g_luamutex;
 LuaContext g_lua;
 
-std::function<shared_ptr<DownstreamState>(const ComboAddress& remote, const DNSName& qname, uint16_t qtype)> g_policy;
+std::function<shared_ptr<DownstreamState>(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)> g_policy;
 
-shared_ptr<DownstreamState> getLuaDownstream(const ComboAddress& remote, const DNSName& qname, uint16_t qtype)
-{
-  //auto pickServer=g_lua.readVariable<LuaContext::LuaFunctionCaller<std::shared_ptr<DownstreamState> (void)> >("pickServer");
-
-  std::lock_guard<std::mutex> lock(g_luamutex);
-
-  auto pickServer=g_lua.readVariable<std::function<std::shared_ptr<DownstreamState>(ComboAddress, DNSName, uint16_t)> >("pickServer");
-  return pickServer(remote, DNSName(qname), qtype);
-}
-
-shared_ptr<DownstreamState> firstAvailable(const ComboAddress& remote, const DNSName& qname, uint16_t qtype)
+shared_ptr<DownstreamState> firstAvailable(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)
 {
   for(auto& d : g_dstates) {
     if(d->isUp() && d->qps.check())
@@ -424,7 +415,7 @@ try
     }
     else {
       std::lock_guard<std::mutex> lock(g_luamutex);
-      ss = g_policy(remote, qname, qtype).get();
+      ss = g_policy(remote, qname, qtype, dh).get();
     }
     ss->queries++;
 
@@ -485,9 +476,12 @@ catch(...)
    Let's start naively.
 */
 
-int getTCPDownstream(DownstreamState** ds, const ComboAddress& remote, const DNSName& qname, uint16_t qtype)
+int getTCPDownstream(DownstreamState** ds, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)
 {
-  *ds = g_policy(remote, qname, qtype).get();
+  {
+    std::lock_guard<std::mutex> lock(g_luamutex);
+    *ds = g_policy(remote, qname, qtype, dh).get();
+  }
   
   vinfolog("TCP connecting to downstream %s", (*ds)->remote.toStringWithPort());
   int sock = SSocket((*ds)->remote.sin4.sin_family, SOCK_STREAM, 0);
@@ -578,13 +572,6 @@ void* tcpClientThread(int pipefd)
     ci=*citmp;
     delete citmp;
      
-    if(dsock == -1) {
-
-      dsock = getTCPDownstream(&ds, ci.remote, DNSName(), 0);
-    }
-    else {
-      vinfolog("Reusing existing TCP connection to %s", ds->remote.toStringWithPort());
-    }
 
     uint16_t qlen, rlen;
     try {
@@ -596,12 +583,22 @@ void* tcpClientThread(int pipefd)
         ds->outstanding++;
         char query[qlen];
         readn2(ci.fd, query, qlen);
+       uint16_t qtype;
+       DNSName qname(query, qlen, 12, false, &qtype);
+       struct dnsheader* dh =(dnsheader*)query;
+       if(dsock == -1) {
+         dsock = getTCPDownstream(&ds, ci.remote, qname, qtype, dh);
+       }
+       else {
+         vinfolog("Reusing existing TCP connection to %s", ds->remote.toStringWithPort());
+       }
+
         // FIXME: drop AXFR queries here, they confuse us
       retry:; 
         if(!putMsgLen(dsock, qlen)) {
          vinfolog("Downstream connection to %s died on us, getting a new one!", ds->remote.toStringWithPort());
           close(dsock);
-          dsock=getTCPDownstream(&ds, ci.remote, DNSName(), 0);
+          dsock=getTCPDownstream(&ds, ci.remote, qname, qtype, dh);
           goto retry;
         }
       
@@ -610,7 +607,7 @@ void* tcpClientThread(int pipefd)
         if(!getMsgLen(dsock, &rlen)) {
          vinfolog("Downstream connection to %s died on us phase 2, getting a new one!", ds->remote.toStringWithPort());
           close(dsock);
-          dsock=getTCPDownstream(&ds, ci.remote, DNSName(), 0);
+          dsock=getTCPDownstream(&ds, ci.remote, qname, qtype, dh);
           goto retry;
         }
 
@@ -854,7 +851,7 @@ void setupLua(bool client)
                      } );
 
 
-  g_lua.writeFunction("setServerPolicy", [](std::function<shared_ptr<DownstreamState>(const ComboAddress&, const DNSName&, uint16_t)> func) {
+  g_lua.writeFunction("setServerPolicy", [](std::function<shared_ptr<DownstreamState>(const ComboAddress&, const DNSName&, uint16_t, dnsheader*)> func) {
       g_policy = func;
     });
 
@@ -944,6 +941,11 @@ void setupLua(bool client)
       dh.rd=v;
     });
 
+  g_lua.registerFunction<bool(dnsheader::*)()>("getRD", [](dnsheader& dh) {
+      return (bool)dh.rd;
+    });
+
+
   g_lua.registerFunction<void(dnsheader::*)(bool)>("setTC", [](dnsheader& dh, bool v) {
       dh.tc=v;
     });
index 17941d02e0701060931ed002d1b2b5ac04bb9b59..12b64037fdb7d54d1ea9a9fa6c5c8e168b4642ba 100644 (file)
@@ -43,10 +43,20 @@ counter=0
 servers=getServers()
 
 -- called to pick a downstream server
-function luaroundrobin(remote, qname, qtype) 
+function luaroundrobin(remote, qname, qtype, dh
         counter=counter+1;
         return servers[1+(counter % #servers)]
 end
 
 -- setServerPolicy(luaroundrobin)
 
+authServer=newServer2{address="2001:888:2000:1d::2", order=12}
+
+function splitSetup(remote, qname, qtype, dh)
+        if(dh:getRD() == false)
+        then
+               return authServer
+        else
+               return firstAvailable(remote, qname, qtype, dh)
+        end
+end
\ No newline at end of file