Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getPool(""):getCache():dump("/tmp/myfile.txt") -- doesn't dump ECS values #14649

Open
2 tasks done
PenelopeFudd opened this issue Sep 9, 2024 · 10 comments
Open
2 tasks done

Comments

@PenelopeFudd
Copy link

PenelopeFudd commented Sep 9, 2024

  • Program: dnsdist
  • Issue type: Bug report

Short description

With DNSDist, if you dump a cache to disk, it doesn't include all of the cached information. Specifically, it doesn't include ECS subnet information.

Environment

  • Operating system: Ubuntu 22.04
  • Software version: 1.9.6
  • Software source: DNSDist repository

Steps to reproduce

  1. dnsdist -k "$password" -c 127.0.0.1:1111 -C /dev/null <<< 'getPool("pdns"):getCache():dump("/tmp/dnsdist-dump")'
  2. more /tmp/dnsdist-dump

Expected behaviour

; dnsdist's packet cache dump follows
;
v1.pv-txt.pool.dns.net. 23 TXT scope 11.22.33.44/24; rcode 0, key 2867384720, length 394, received over UDP 1, added 1725921938
v1.pv-txt.pool.dns.net. 22 TXT scope 11.22.55.66/24; rcode 0, key 3176530280, length 394, received over UDP 1, added 1725921937

Actual behaviour

; dnsdist's packet cache dump follows
;
v1.pv-txt.pool.dns.net. 23 TXT ; rcode 0, key 2867384720, length 394, received over UDP 1, added 1725921938
v1.pv-txt.pool.dns.net. 22 TXT ; rcode 0, key 3176530280, length 394, received over UDP 1, added 1725921937

Other information

Actually, would it be possible to see the answers, and not just their lengths?

Thanks!

@phonedph1
Copy link
Contributor

Hrm - maybe something like this (but with qtype/qclass in proper positions) - includes qclass, subnet and DO bit. Is there a 'nice' way to print query flags too?

I was half into this a few months ago but never got around to finishing it.

-        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<int64_t>(value.validity - now), QType(value.qtype).toString().c_str(), rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast<int64_t>(value.added));
+        fprintf(filePtr.get(), "%s %" PRId64 " %s %s ; scope %s, rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 ", dnssec %d\n", value.qname.toString().c_str(), static_cast<int64_t>(value.validity - now), QType(value.qtype).toString().c_str(), QClass(value.qclass).toString().c_str(), value.subnet ? value.subnet.get().toString().c_str() : "", rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast<int64_t>(value.added), value.dnssecOK ? 1 : 0);
; dnsdist's packet cache dump follows
;
google.com. 293 A IN ; scope 8.8.8.0/24, rcode 0, key 2426484888, length 66, received over UDP 1, added 1725937615, dnssec 0
google.com. 25 TXT CHAOS ; scope 1.2.4.0/24, rcode 2, key 4091352989, length 50, received over UDP 1, added 1725937587, dnssec 1
google.com. 17 TXT CHAOS ; scope ::/128, rcode 2, key 556335832, length 63, received over UDP 1, added 1725937579, dnssec 0
google.com. 298 A IN ; scope 8.8.8.0/24, rcode 0, key 3904309213, length 66, received over UDP 1, added 1725937620, dnssec 1
google.com. 22 TXT CHAOS ; scope 1.2.4.0/24, rcode 2, key 4244306876, length 50, received over UDP 1, added 1725937584, dnssec 0
google.com. 49 A IN ; scope , rcode 5, key 227726898, length 39, received over UDP 1, added 1725937611, dnssec 0

@rgacogne
Copy link
Member

Actually, would it be possible to see the answers, and not just their lengths?

Unfortunately dnsdist doesn't know how to parse most of the DNS records, because it doesn't have to, and we would like to keep it that way to reduce the amount of complexity. We could display the content of the response without decoding the content of records, just their owner names, types, classes and lengths. We might also offer an option to dump the raw (hex?) content of records.

@phonedph1 looks like a nice improvement, would you like to PR it? :)

@PenelopeFudd
Copy link
Author

As long as I can see everything in the cache (in hex if nothing else), with some indication as to what parts are being used as the cache key and what the initial and current ttl are, that'd be nice.
If there was a way to dump the packets in a mocked-up pcap form (i.e. dummy source/destination), then parsing could be done with an external program (tcpdump/wireshark/etc).

@Habbie
Copy link
Member

Habbie commented Sep 10, 2024

sidenote: base64 would be shorter

@Habbie
Copy link
Member

Habbie commented Sep 10, 2024

If there was a way to dump the packets in a mocked-up pcap form (i.e. dummy source/destination), then parsing could be done with an external program (tcpdump/wireshark/etc).

sdig from pdns-utils can parse packets from stdin, so if we have hex or base64 full packets, that would be as simple as echo [base64 goes here] | openssl base64 -d | sdig stdin 0 . A

@Habbie
Copy link
Member

Habbie commented Sep 10, 2024

note to self: sdig says Reply to question for .. even when I hand it a query packet.

@phonedph1
Copy link
Contributor

phonedph1 commented Sep 10, 2024

Amazing.

; dnsdist's packet cache dump follows
;
powerdns.com. 292 IN A ; ecs 70.0.0.0/8, rcode 0, key 3175689385, length 254, received over UDP 1, added 1726003963, dnssecOK 1, base64response 94CBoAABAAMAAAABCHBvd2VyZG5zA2NvbQAAAQABwAwAAQABAAABLAAExzxnocAMAAEAAQAAASwABMc8Zz3ADAAuAAEAAAEsAKAAAQgCAAABLGbraYBmz7oAjLUIcG93ZXJkbnMDY29tAEYxPKnCR4OBvr28SQdRYoUy5WHBg1gYo5+WAHlbjyvPY8lIST23ueA6l5HG5xFicGUhF7CLoTZsSF7KigGogTbQMdQCnr8CaUMGSjhHa2DdTzLgS9lhaSYrII2aIyJMCzm6gnJhjpANhhm4Ijde10aya3fbYIBeVplVs1QRLKw/AAApAgAAAIAAAAkACAAFAAEIAEY=
powerdns.com. 55 IN A ; ecs empty, rcode 5, key 1913889586, length 41, received over UDP 1, added 1726003966, dnssecOK 0, base64response fcmBhQABAAAAAAABCHBvd2VyZG5zA2NvbQAAAQABAAApAgAAAAAAAAA=
$ echo 94CBoAABAAMAAAABCHBvd2VyZG5zA2NvbQAAAQABwAwAAQABAAABLAAExzxnocAMAAEAAQAAASwABMc8Zz3ADAAuAAEAAAEsAKAAAQgCAAABLGbraYBmz7oAjLUIcG93ZXJkbnMDY29tAEYxPKnCR4OBvr28SQdRYoUy5WHBg1gYo5+WAHlbjyvPY8lIST23ueA6l5HG5xFicGUhF7CLoTZsSF7KigGogTbQMdQCnr8CaUMGSjhHa2DdTzLgS9lhaSYrII2aIyJMCzm6gnJhjpANhhm4Ijde10aya3fbYIBeVplVs1QRLKw/AAApAgAAAIAAAAkACAAFAAEIAEY= | base64 -d | ./sdig stdin 0 . A
ID 63360 was not expected, this response was not meant for us!
Reply to question for qname='powerdns.com.', qtype=A
Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
0	powerdns.com.	300	IN	A	199.60.103.161
0	powerdns.com.	300	IN	A	199.60.103.61
0	powerdns.com.	300	IN	RRSIG	A 8 2 300 [expiry] [inception] [keytag] powerdns.com. ...
2	.	32768	IN	OPT	AAgABQABCABG
EDNS Subnet response: 70.0.0.0/8, scope: 0.0.0.0/0, family = 2
index d6323d8b3..f5cb1399d 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<int64_t>(value.validity - now), QType(value.qtype).toString().c_str(), rcode, entry.first, value.len, value.receivedOverUDP ? 1 : 0, static_cast<int64_t>(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, base64response %s\n", value.qname.toString().c_str(), static_cast<int64_t>(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<int64_t>(value.added), value.dnssecOK ? 1 : 0, rawResponse.c_str());
       }
       catch (...) {
         fprintf(filePtr.get(), "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str());

@PenelopeFudd
Copy link
Author

Should we do anything about the "ID 63360 was not expected, this response was not meant for us!" message?
Although for the life of me I can't think of what would make sense:

  • Prepending a fake question?
  • Setting the ID to 0 and having sdig skip that warning for answers with an ID of zero?
  • Adding a flag to sdig that says "don't print that warning, I don't care"
  • | grep -v "not meant for us"
  • Live with it

@Habbie
Copy link
Member

Habbie commented Sep 12, 2024

Should we do anything about the "ID 63360 was not expected, this response was not meant for us!" message?

that plus the thing I noted probably warrant a separate ticket about "improving sdig stdin". Want to do those honours?

@Habbie
Copy link
Member

Habbie commented Sep 12, 2024

that plus the thing I noted probably warrant a separate ticket about "improving sdig stdin".

this directly became PR #14665. Let me know there if you can think of any other relevant improvements :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants