]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add an option to 'mute' UDP responses per bind 4536/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 5 Oct 2016 09:28:40 +0000 (11:28 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 9 Dec 2016 08:21:05 +0000 (09:21 +0100)
pdns/README-dnsdist.md
pdns/dnsdist-lua2.cc
pdns/dnsdist.cc
pdns/dnsdist.hh

index b9521c2984eeda6f184f936f80906b3bf2fe040d..d64366abed295480ff142d67ec8e7a349cf09e30 100644 (file)
@@ -1234,6 +1234,7 @@ Here are all functions:
     * function `getBind(n)`: return the corresponding `ClientState` object
     * member `attachFilter(BPFFilter)`: attach a BPF Filter to this bind
     * member `detachFilter()`: detach the BPF Filter attached to this bind, if any
+    * member `muted`: if set to true, UDP responses will not be sent for queries received on this bind. Default to false
     * member `toString()`: print the address this bind listens to
  * Network related:
     * `addLocal(netmask, [true], [false], [TCP Fast Open queue size])`: add to addresses we listen on. Second optional parameter sets TCP or not. Third optional parameter sets SO_REUSEPORT when available. Last parameter sets the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0.
index a5e27495e026ac971be22f86fc82cc7812f9767b..e434c23b033751b07eea1e7b1652f77cb9739487 100644 (file)
@@ -879,6 +879,8 @@ void moreLua(bool client)
         return fe.local.toStringWithPort();
       });
 
+    g_lua.registerMember("muted", &ClientState::muted);
+
     g_lua.writeFunction("help", [](boost::optional<std::string> command) {
         setLuaNoSideEffect();
         g_outputBuffer = "";
index b0eaacfd9fc9bf5315279ebe9b14950c70d06c62..76b8543fd28df16be72704e09309e20c3f65765b 100644 (file)
@@ -428,16 +428,19 @@ try {
         ids->packetCache->insert(ids->cacheKey, ids->qname, ids->qtype, ids->qclass, response, responseLen, false, dh->rcode == RCode::ServFail);
       }
 
+      if (ids->cs && !ids->cs->muted) {
 #ifdef HAVE_DNSCRYPT
-      if (!encryptResponse(response, &responseLen, responseSize, false, ids->dnsCryptQuery)) {
-        continue;
-      }
+        if (!encryptResponse(response, &responseLen, responseSize, false, ids->dnsCryptQuery)) {
+          continue;
+        }
 #endif
-      ComboAddress empty;
-      empty.sin4.sin_family = 0;
-      /* if ids->destHarvested is false, origDest holds the listening address.
-         We don't want to use that as a source since it could be 0.0.0.0 for example. */
-      sendUDPResponse(origFD, response, responseLen, ids->delayMsec, ids->destHarvested ? ids->origDest : empty, ids->origRemote);
+
+        ComboAddress empty;
+        empty.sin4.sin_family = 0;
+        /* if ids->destHarvested is false, origDest holds the listening address.
+           We don't want to use that as a source since it could be 0.0.0.0 for example. */
+        sendUDPResponse(origFD, response, responseLen, ids->delayMsec, ids->destHarvested ? ids->origDest : empty, ids->origRemote);
+      }
 
       g_stats.responses++;
 
@@ -1067,12 +1070,15 @@ try
 
         restoreFlags(dh, origFlags);
 
+        if (!cs->muted) {
 #ifdef HAVE_DNSCRYPT
-        if (!encryptResponse(response, &responseLen, dq.size, false, dnsCryptQuery)) {
-          continue;
-        }
+          if (!encryptResponse(response, &responseLen, dq.size, false, dnsCryptQuery)) {
+            continue;
+          }
 #endif
-        sendUDPResponse(cs->udpFD, response, responseLen, 0, dest, remote);
+          sendUDPResponse(cs->udpFD, response, responseLen, 0, dest, remote);
+        }
+
         continue;
       }
 
@@ -1098,12 +1104,15 @@ try
         uint16_t cachedResponseSize = sizeof cachedResponse;
         uint32_t allowExpired = ss ? 0 : g_staleCacheEntriesTTL;
         if (packetCache->get(dq, consumed, dh->id, cachedResponse, &cachedResponseSize, &cacheKey, allowExpired)) {
+          if (!cs->muted) {
 #ifdef HAVE_DNSCRYPT
-          if (!encryptResponse(cachedResponse, &cachedResponseSize, sizeof cachedResponse, false, dnsCryptQuery)) {
-            continue;
-          }
+            if (!encryptResponse(cachedResponse, &cachedResponseSize, sizeof cachedResponse, false, dnsCryptQuery)) {
+              continue;
+            }
 #endif
-          sendUDPResponse(cs->udpFD, cachedResponse, cachedResponseSize, 0, dest, remote);
+            sendUDPResponse(cs->udpFD, cachedResponse, cachedResponseSize, 0, dest, remote);
+          }
+
           g_stats.cacheHits++;
           g_stats.latency0_1++;  // we're not going to measure this
           doLatencyAverages(0);  // same
@@ -1146,6 +1155,7 @@ try
         g_stats.downstreamTimeouts++;
       }
 
+      ids->cs = cs;
       ids->origFD = cs->udpFD;
       ids->origID = dh->id;
       ids->origRemote = remote;
index a8d877fbab9b66fbdcec012a4082cc5438bab2f5..f5bac471198d89acc1295196ac6a6ec8faaf11ae 100644 (file)
@@ -233,6 +233,8 @@ private:
   mutable unsigned int d_blocked{0};
 };
 
+struct ClientState;
+
 struct IDState
 {
   IDState() : origFD(-1), sentTime(true), delayMsec(0) { origDest.sin4.sin_family = 0;}
@@ -259,6 +261,7 @@ struct IDState
   boost::uuids::uuid uniqueId;
 #endif
   std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
+  const ClientState* cs{nullptr};
   uint32_t cacheKey;                                          // 8
   std::atomic<uint16_t> age;                                  // 4
   uint16_t qtype;                                             // 2
@@ -334,6 +337,7 @@ struct ClientState
   std::atomic<uint64_t> queries{0};
   int udpFD{-1};
   int tcpFD{-1};
+  bool muted{false};
 
   int getSocket() const
   {