From beb053524fe8d28a2662d7fce1fa5c1a074e6dd8 Mon Sep 17 00:00:00 2001 From: Victor Roemer Date: Tue, 3 Sep 2024 23:45:19 +0000 Subject: [PATCH] DNS Initial Support --- Containerfile | 2 +- {piglet-bpf-filter => bin}/.gitignore | 0 {piglet-bpf-filter => bin}/Makefile | 2 +- {piglet-bpf-filter => bin}/daq_print.cc | 35 +++---- {piglet-bpf-filter => bin}/daq_print.h | 0 .../piglet-bpf-filter.cc => bin/dns_hog.cc | 16 ++- bin/pcaps/dns-label-loop.pcap | Bin 0 -> 216 bytes {piglet-bpf-filter => bin}/pcaps/dns.pcap | Bin include/packet/dns.h | 2 +- src/dns.cc | 96 +++++++++++------- 10 files changed, 90 insertions(+), 63 deletions(-) rename {piglet-bpf-filter => bin}/.gitignore (100%) rename {piglet-bpf-filter => bin}/Makefile (63%) rename {piglet-bpf-filter => bin}/daq_print.cc (91%) rename {piglet-bpf-filter => bin}/daq_print.h (100%) rename piglet-bpf-filter/piglet-bpf-filter.cc => bin/dns_hog.cc (97%) create mode 100644 bin/pcaps/dns-label-loop.pcap rename {piglet-bpf-filter => bin}/pcaps/dns.pcap (100%) diff --git a/Containerfile b/Containerfile index 46cf0c9..9096adf 100644 --- a/Containerfile +++ b/Containerfile @@ -1,5 +1,5 @@ # Using www.github.com/wtfbbqhax/krakatoa -FROM arm64v8/krakatoa AS libpacket_dev_env +FROM amd64/krakatoa AS libpacket_dev_env USER root RUN apk update diff --git a/piglet-bpf-filter/.gitignore b/bin/.gitignore similarity index 100% rename from piglet-bpf-filter/.gitignore rename to bin/.gitignore diff --git a/piglet-bpf-filter/Makefile b/bin/Makefile similarity index 63% rename from piglet-bpf-filter/Makefile rename to bin/Makefile index 0b8225d..39482c2 100644 --- a/piglet-bpf-filter/Makefile +++ b/bin/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/env bash -piglet-bpf-filter: piglet-bpf-filter.cc daq_print.cc daq_print.h +dns-hog: dns_hog.cc daq_print.cc daq_print.h c++ -ggdb -std=c++14 -lstdc++ $^ -lpcap -ldaq -lpacket -o $@ clean: diff --git a/piglet-bpf-filter/daq_print.cc b/bin/daq_print.cc similarity index 91% rename from piglet-bpf-filter/daq_print.cc rename to bin/daq_print.cc index 2b64df3..73fc4eb 100644 --- a/piglet-bpf-filter/daq_print.cc +++ b/bin/daq_print.cc @@ -36,9 +36,9 @@ int print_dns(dns const& dns) { bool is_response = DNS_QR(dns.h.flags); - if (is_response) + //if (is_response) { - printf("[dns response] [rcode:%d, id:%d, qdcount: %d, ancount: %d, nscount: %d, arcount:%d]\n", + printf("[dns] [rcode:%d, id:%d, qdcount: %d, ancount: %d, nscount: %d, arcount:%d]\n", DNS_RCODE(dns.h.flags), dns.h.id, dns.h.qdcount, @@ -46,12 +46,12 @@ int print_dns(dns const& dns) dns.h.nscount, dns.h.arcount); } - else - { - printf("[dns query] [id:%d, qdcount: %d]\n", - dns.h.id, - dns.h.qdcount); - } + //else + //{ + // printf("[dns query] [id:%d, qdcount: %d]\n", + // dns.h.id, + // dns.h.qdcount); + //} // Parsing Question Section for (int i = 0; i < dns.h.qdcount; i++) @@ -78,7 +78,11 @@ int print_dns(dns const& dns) { inet_ntop(AF_INET, a.data.data(), addr, sizeof(addr)); human.append(addr, strnlen(addr, INET6_ADDRSTRLEN)); - + } + else if (a.dns_atype == 28) + { + inet_ntop(AF_INET6, a.data.data(), addr, sizeof(addr)); + human.append(addr, strnlen(addr, INET6_ADDRSTRLEN)); } else { @@ -95,6 +99,7 @@ int print_dns(dns const& dns) // (void)dns[0].questions[i].dns_qclass; } + printf("\n"); return 0; } @@ -179,21 +184,17 @@ print_packet(int const instance_id, DAQ_PktHdr_t const* hdr, uint8_t const * dat packet_frag_mf(&packet) ? "mf" : ""); } + uint32_t max = packet_paysize(&packet); + const uint8_t *payload = packet_payload(&packet); if (sport == 53 || dport == 53) { dns _dns; - decode_dns(packet_payload(&packet), - packet_paysize(&packet), - &_dns); + decode_dns(payload, max, &_dns); print_dns(_dns); } - uint32_t max = packet_paysize(&packet); - const uint8_t *payload = packet_payload(&packet); max = max > 128 ? 128 : max; - print_data(payload, max); - - //print_data(data, len); + //print_data(payload, max); #ifdef PRINT_PACKET_STATS // Packet stats are useful for determining decoding errors diff --git a/piglet-bpf-filter/daq_print.h b/bin/daq_print.h similarity index 100% rename from piglet-bpf-filter/daq_print.h rename to bin/daq_print.h diff --git a/piglet-bpf-filter/piglet-bpf-filter.cc b/bin/dns_hog.cc similarity index 97% rename from piglet-bpf-filter/piglet-bpf-filter.cc rename to bin/dns_hog.cc index d70c3b8..ad60f2e 100644 --- a/piglet-bpf-filter/piglet-bpf-filter.cc +++ b/bin/dns_hog.cc @@ -21,9 +21,7 @@ #include #include -//#include -//#include - +#define TXT_FG_PURPLE(str) "\e[35m" str "\e[0m" #include "daq_print.h" @@ -441,7 +439,8 @@ class DataPlaneWorker } verdicts.verdicts[i] = verdict; - printf(matched ? "[match|%s] " : "[%s]", str_from_verdict(verdict)); + printf(matched ? "[" TXT_FG_PURPLE("match") "] " : ""); + printf("[%s] ", str_from_verdict(verdict)); print_packet(id, hdr, data, hdr->pktlen); } } @@ -508,9 +507,9 @@ int main(int argc, char const* argv[]) //{ "debug", "true" }, }; - if (argc < 3) + if (argc < 2) { - fprintf(stderr, "Usage: piglet-bpf-filter [pass|block|allowlist|blocklist] \n"); + fprintf(stderr, "Usage: piglet-bpf-filter \n"); exit(1); } @@ -520,13 +519,12 @@ int main(int argc, char const* argv[]) DaqConfig pcap_config("pcap", "pcaps/dns.pcap", DAQ_MODE_READ_FILE, vars); DataPlaneWorker wk0(pcap_config, 0, filter, match_verdict, default_verdict); + sleep(2); + wk0.stop(); wk0.join(); - //DataPlaneWorker wk1(vpp_inline_config, 1, filter, match_verdict, default_verdict); - //wk1.stop(); wk1.join(); - DAQ::unload_modules(); return 0; } diff --git a/bin/pcaps/dns-label-loop.pcap b/bin/pcaps/dns-label-loop.pcap new file mode 100644 index 0000000000000000000000000000000000000000..0470c58833f24feabaf8df6824faf6083ae52ff5 GIT binary patch literal 216 zcmca|c+)~A1{MYw`2U}Qff2|t@7kiyB}3}k~a6DJ2d8!Hnd6Eh1d2ZJjEgDFUv zgJ8@OE}$3}P(ptr), label_len); + _label.append("."); + ptr += label_len; + + if (ptr[0] != 0) { + goto scan_again; + } +} + // Function to decode the DNS protocol -int +extern "C" int decode_dns(uint8_t const * pkt, uint32_t const len, dns* dns) { if (len < MINIMUM_DNS_HEADER_SIZE) { @@ -113,8 +144,23 @@ decode_dns(uint8_t const * pkt, uint32_t const len, dns* dns) s_dns_stats.dns_tooshort++; return -1; } - // FIXME: Store this value? - uint16_t name = ntohs(*(uint16_t *)ptr); + + // The "name" appears to be a partial label, but I can't find that + // documented in rfc1035, more testing is needed. + std::string name; + if (IS_SET(ptr[0], 0xC0)) { + uint8_t off = ptr[1]; + uint8_t const* label = &pkt[off]; + uint8_t label_len = *label; + while(label[0] != 0) + { + label++; + name.append(reinterpret_cast(label), label_len); + name.append("."); + label += label_len; + } + } + ptr += 2; remaining_len -= 2; @@ -150,43 +196,25 @@ decode_dns(uint8_t const * pkt, uint32_t const len, dns* dns) return -1; } - const uint8_t *rdata = ptr; - ptr += rdlength; - remaining_len -= rdlength; - - // Store answer information (assuming a structure in Packet to store this information) + // Store answer information (assuming a structure in Packet to store + // this information) a->dns_atype = atype; a->dns_aclass = aclass; a->dns_ttl = ttl; - // Parse rdata - while (rdata < ptr) + if (atype == 1 || atype == 28) { - uint16_t us = *reinterpret_cast(rdata); - if (us == name) - { - rdata += 2; - rdlength -= 2; - continue; - } - - uint8_t len = 0; - if (rdlength >= 1) - { - len = *rdata; - rdata += 1; - } - // abort if len == 0 && rdatalength > 0 // ANOMALY? - - len = rdlength > len ? len : rdlength; - - if (len) - { - a->data.append(reinterpret_cast(rdata), len); - a->data.append("."); - } - rdata += len; + a->data.append(reinterpret_cast(ptr), rdlength); + } + else + { + // Parse rdata + decode_label(pkt, ptr, a->data); } + + //const uint8_t *rdata = ptr; + ptr += rdlength; + remaining_len -= rdlength; } return 0;