From d0f519b5179fb0875a885f03dbad6834464ecfac Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Tue, 10 Sep 2024 19:51:03 -0600 Subject: [PATCH 1/7] Dump more packet cache info: ECS subnet, DO, raw query flags, and base64 encoded response --- pdns/dnsdistdist/dnsdist-cache.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pdns/dnsdistdist/dnsdist-cache.cc b/pdns/dnsdistdist/dnsdist-cache.cc index d6323d8b3224..5ce24c28d4ec 100644 --- a/pdns/dnsdistdist/dnsdist-cache.cc +++ b/pdns/dnsdistdist/dnsdist-cache.cc @@ -28,6 +28,7 @@ #include "dnsdist-ecs.hh" #include "ednssubnet.hh" #include "packetcache.hh" +#include "base64.hh" // NOLINTNEXTLINE(bugprone-easily-swappable-parameters): too cumbersome to change at this point DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t maxNegativeTTL, uint32_t staleTTL, bool dontAge, uint32_t shards, bool deferrableInsertLock, bool parseECS) : @@ -507,7 +508,8 @@ uint64_t DNSDistPacketCache::dump(int fileDesc) rcode = dnsHeader.rcode; } - fprintf(filePtr.get(), "%s %" PRId64 " %s ; rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 "\n", value.qname.toString().c_str(), static_cast(value.validity - now), QType(value.qtype).toString().c_str(), rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast(value.added)); + std::string rawResponse = Base64Encode(value.value); + fprintf(filePtr.get(), "%s %" PRId64 " %s %s ; ecs %s, rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 ", dnssecOK %d, raw query flags %" PRIu16 ", base64response %s\n", value.qname.toString().c_str(), static_cast(value.validity - now), QClass(value.qclass).toString().c_str(), QType(value.qtype).toString().c_str(), value.subnet ? value.subnet.get().toString().c_str() : "empty", rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast(value.added), value.dnssecOK ? 1 : 0, value.queryFlags, rawResponse.c_str()); } catch (...) { fprintf(filePtr.get(), "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str()); From dbebb9c8a662f47b85723a63edeb0d8d28bbee20 Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Thu, 12 Sep 2024 07:00:37 -0600 Subject: [PATCH 2/7] Make fuzzer happy? --- pdns/dnsdistdist/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index fc0a25ffd646..206355bf7137 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -556,6 +556,7 @@ fuzz_target_dnsdistcache_SOURCES = \ dns.cc dns.hh \ dnsdist-cache.cc dnsdist-cache.hh \ dnsdist-configuration.cc dnsdist-configuration.hh \ + dnsdist-crypto.cc dnsdist-crypto.hh \ dnsdist-dnsparser.cc dnsdist-dnsparser.hh \ dnsdist-dnsquestion.cc \ dnsdist-ecs.cc dnsdist-ecs.hh \ From 25781b1700c29018ae6bb2fef2f3876ecd9d3558 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 12 Sep 2024 17:53:35 +0200 Subject: [PATCH 3/7] dnsdist: Add now needed sodium libs to the cache fuzzer --- pdns/dnsdistdist/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 206355bf7137..14ee65d2fe80 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -538,8 +538,9 @@ bin_PROGRAMS += \ $(fuzz_targets_programs) fuzz_targets_libs = \ - $(LIBCRYPTO_LIBS) \ $(ARC4RANDOM_LIBS) \ + $(LIBCRYPTO_LIBS) \ + $(LIBSODIUM_LIBS) \ $(LIB_FUZZING_ENGINE) fuzz_targets_ldflags = \ From 7178635c3788c5cfb0b964f2185b81c26576c779 Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Wed, 18 Sep 2024 20:12:08 -0600 Subject: [PATCH 4/7] make the more dumping optional --- pdns/dnsdistdist/dnsdist-cache.cc | 11 ++++++++--- pdns/dnsdistdist/dnsdist-cache.hh | 2 +- pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc | 4 ++-- pdns/dnsdistdist/docs/reference/config.rst | 6 +++++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-cache.cc b/pdns/dnsdistdist/dnsdist-cache.cc index 5ce24c28d4ec..8baf99b41099 100644 --- a/pdns/dnsdistdist/dnsdist-cache.cc +++ b/pdns/dnsdistdist/dnsdist-cache.cc @@ -482,7 +482,7 @@ uint64_t DNSDistPacketCache::getEntriesCount() return getSize(); } -uint64_t DNSDistPacketCache::dump(int fileDesc) +uint64_t DNSDistPacketCache::dump(int fileDesc, bool rawResponse) { auto filePtr = pdns::UniqueFilePtr(fdopen(dup(fileDesc), "w")); if (filePtr == nullptr) { @@ -508,8 +508,13 @@ uint64_t DNSDistPacketCache::dump(int fileDesc) rcode = dnsHeader.rcode; } - std::string rawResponse = Base64Encode(value.value); - fprintf(filePtr.get(), "%s %" PRId64 " %s %s ; ecs %s, rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 ", dnssecOK %d, raw query flags %" PRIu16 ", base64response %s\n", value.qname.toString().c_str(), static_cast(value.validity - now), QClass(value.qclass).toString().c_str(), QType(value.qtype).toString().c_str(), value.subnet ? value.subnet.get().toString().c_str() : "empty", rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast(value.added), value.dnssecOK ? 1 : 0, value.queryFlags, rawResponse.c_str()); + fprintf(filePtr.get(), "%s %" PRId64 " %s %s ; ecs %s, rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 ", dnssecOK %d, raw query flags %" PRIu16, value.qname.toString().c_str(), static_cast(value.validity - now), QClass(value.qclass).toString().c_str(), QType(value.qtype).toString().c_str(), value.subnet ? value.subnet.get().toString().c_str() : "empty", rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast(value.added), value.dnssecOK ? 1 : 0, value.queryFlags); + + if (rawResponse) { + std::string rawDataResponse = Base64Encode(value.value); + fprintf(filePtr.get(), ", base64response %s", rawDataResponse.c_str()); + } + fprintf(filePtr.get(), "\n"); } catch (...) { fprintf(filePtr.get(), "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str()); diff --git a/pdns/dnsdistdist/dnsdist-cache.hh b/pdns/dnsdistdist/dnsdist-cache.hh index b26fb5f666f3..241cf98f402f 100644 --- a/pdns/dnsdistdist/dnsdist-cache.hh +++ b/pdns/dnsdistdist/dnsdist-cache.hh @@ -55,7 +55,7 @@ public: uint64_t getTTLTooShorts() const { return d_ttlTooShorts.load(); } uint64_t getCleanupCount() const { return d_cleanupCount.load(); } uint64_t getEntriesCount(); - uint64_t dump(int fileDesc); + uint64_t dump(int fileDesc, bool fullResponse = false); /* get the list of domains (qnames) that contains the given address in an A or AAAA record */ std::set getDomainsContainingRecords(const ComboAddress& addr); diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc index 65470b2b870d..30a09d6c4c24 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc @@ -202,7 +202,7 @@ void setupLuaBindingsPacketCache(LuaContext& luaCtx, bool client) return results; }); - luaCtx.registerFunction::*)(const std::string& fname)const>("dump", [](const std::shared_ptr& cache, const std::string& fname) { + luaCtx.registerFunction::*)(const std::string& fname, boost::optional rawResponse)const>("dump", [](const std::shared_ptr& cache, const std::string& fname, boost::optional rawResponse) { if (cache) { int fd = open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660); @@ -213,7 +213,7 @@ void setupLuaBindingsPacketCache(LuaContext& luaCtx, bool client) uint64_t records = 0; try { - records = cache->dump(fd); + records = cache->dump(fd, rawResponse? *rawResponse : false); } catch (const std::exception& e) { close(fd); diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 94d3de533da6..f32e06405e53 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -1004,11 +1004,15 @@ See :doc:`../guides/cache` for a how to. Represents a cache that can be part of :class:`ServerPool`. - .. method:: PacketCache:dump(fname) + .. method:: PacketCache:dump(fname [, rawResponse=false]) + + .. versionchanged:: 2.0.0 + ``rawResponse`` added Dump a summary of the cache entries to a file. :param str fname: The path to a file where the cache summary should be dumped. Note that if the target file already exists, it will not be overwritten. + :param bool rawResponse: Dump the raw packet response encoded with base64. .. method:: PacketCache:expunge(n) From d26cc83c4492780160909d5a6b5a217fc25dc268 Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Wed, 18 Sep 2024 20:15:52 -0600 Subject: [PATCH 5/7] fix naming --- pdns/dnsdistdist/dnsdist-cache.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdns/dnsdistdist/dnsdist-cache.hh b/pdns/dnsdistdist/dnsdist-cache.hh index 241cf98f402f..a3ef35023e4c 100644 --- a/pdns/dnsdistdist/dnsdist-cache.hh +++ b/pdns/dnsdistdist/dnsdist-cache.hh @@ -55,7 +55,7 @@ public: uint64_t getTTLTooShorts() const { return d_ttlTooShorts.load(); } uint64_t getCleanupCount() const { return d_cleanupCount.load(); } uint64_t getEntriesCount(); - uint64_t dump(int fileDesc, bool fullResponse = false); + uint64_t dump(int fileDesc, bool rawResponse = false); /* get the list of domains (qnames) that contains the given address in an A or AAAA record */ std::set getDomainsContainingRecords(const ComboAddress& addr); From 85670d43a8a9b86d63461437ca510d5428cab070 Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Thu, 19 Sep 2024 16:51:23 -0600 Subject: [PATCH 6/7] make formatter happy --- pdns/dnsdistdist/dnsdist-cache.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-cache.cc b/pdns/dnsdistdist/dnsdist-cache.cc index 8baf99b41099..47853bb663c2 100644 --- a/pdns/dnsdistdist/dnsdist-cache.cc +++ b/pdns/dnsdistdist/dnsdist-cache.cc @@ -511,10 +511,10 @@ uint64_t DNSDistPacketCache::dump(int fileDesc, bool rawResponse) fprintf(filePtr.get(), "%s %" PRId64 " %s %s ; ecs %s, rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 ", dnssecOK %d, raw query flags %" PRIu16, value.qname.toString().c_str(), static_cast(value.validity - now), QClass(value.qclass).toString().c_str(), QType(value.qtype).toString().c_str(), value.subnet ? value.subnet.get().toString().c_str() : "empty", rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast(value.added), value.dnssecOK ? 1 : 0, value.queryFlags); if (rawResponse) { - std::string rawDataResponse = Base64Encode(value.value); - fprintf(filePtr.get(), ", base64response %s", rawDataResponse.c_str()); - } - fprintf(filePtr.get(), "\n"); + std::string rawDataResponse = Base64Encode(value.value); + fprintf(filePtr.get(), ", base64response %s", rawDataResponse.c_str()); + } + fprintf(filePtr.get(), "\n"); } catch (...) { fprintf(filePtr.get(), "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str()); From 798c2f1fe53abfd5e6715d44433aff6274a73260 Mon Sep 17 00:00:00 2001 From: phonedph1 Date: Sat, 21 Sep 2024 13:28:27 -0600 Subject: [PATCH 7/7] hint about what to do with the output --- pdns/dnsdistdist/docs/reference/config.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index f32e06405e53..b3952fbd668a 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -1009,7 +1009,7 @@ See :doc:`../guides/cache` for a how to. .. versionchanged:: 2.0.0 ``rawResponse`` added - Dump a summary of the cache entries to a file. + Dump a summary of the cache entries to a file. The raw response packet can be decoded by passing it to ``sdig``: ``echo [base64 encoded packet] | openssl base64 -d | sdig stdin 0 . A`` :param str fname: The path to a file where the cache summary should be dumped. Note that if the target file already exists, it will not be overwritten. :param bool rawResponse: Dump the raw packet response encoded with base64.