From: Remi Gacogne Date: Wed, 5 Oct 2016 09:28:40 +0000 (+0200) Subject: dnsdist: Add an option to 'mute' UDP responses per bind X-Git-Tag: rec-4.1.0-alpha1~332^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b5b93e0b836d3f290f80172efe872bbdfe762bb7;p=thirdparty%2Fpdns.git dnsdist: Add an option to 'mute' UDP responses per bind --- diff --git a/pdns/README-dnsdist.md b/pdns/README-dnsdist.md index b9521c2984..d64366abed 100644 --- a/pdns/README-dnsdist.md +++ b/pdns/README-dnsdist.md @@ -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. diff --git a/pdns/dnsdist-lua2.cc b/pdns/dnsdist-lua2.cc index a5e27495e0..e434c23b03 100644 --- a/pdns/dnsdist-lua2.cc +++ b/pdns/dnsdist-lua2.cc @@ -879,6 +879,8 @@ void moreLua(bool client) return fe.local.toStringWithPort(); }); + g_lua.registerMember("muted", &ClientState::muted); + g_lua.writeFunction("help", [](boost::optional command) { setLuaNoSideEffect(); g_outputBuffer = ""; diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index b0eaacfd9f..76b8543fd2 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -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; diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index a8d877fbab..f5bac47119 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -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 packetCache{nullptr}; + const ClientState* cs{nullptr}; uint32_t cacheKey; // 8 std::atomic age; // 4 uint16_t qtype; // 2 @@ -334,6 +337,7 @@ struct ClientState std::atomic queries{0}; int udpFD{-1}; int tcpFD{-1}; + bool muted{false}; int getSocket() const {