]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4476: dns: adding fallback functionality
authorRishabh Duggal (riduggal) <riduggal@cisco.com>
Wed, 18 Dec 2024 11:41:51 +0000 (11:41 +0000)
committerShibin K V (shikv) <shikv@cisco.com>
Wed, 18 Dec 2024 11:41:51 +0000 (11:41 +0000)
Merge in SNORT/snort3 from ~RIDUGGAL/snort3:dns_fallback to master

Squashed commit of the following:

commit 9ef5c14e1f1ebc5d2b62e23326bc10c6de931b29
Author: riduggal <riduggal@cisco.com>
Date:   Tue Oct 8 10:29:36 2024 +0000

    dns: adding fallback functionality

src/service_inspectors/dns/dns.cc
src/service_inspectors/dns/dns.h
src/service_inspectors/dns/dns_module.h
src/service_inspectors/dns/dns_splitter.cc

index 5dc827d6eea72f0c2c0df8c9a9e09bda7b62cfb7..78951c4a6253fba65b204b0b7ea904128ad32415 100644 (file)
@@ -31,7 +31,6 @@
 #include "dns_config.h"
 #include "log/messages.h"
 #include "profiler/profiler.h"
-#include "protocols/packet.h"
 #include "stream/stream.h"
 
 #include "dns_module.h"
@@ -53,6 +52,7 @@ const PegInfo dns_peg_names[] =
     { CountType::SUM, "responses", "total dns responses" },
     { CountType::NOW, "concurrent_sessions", "total concurrent dns sessions" },
     { CountType::MAX, "max_concurrent_sessions", "maximum concurrent dns sessions" },
+    { CountType::SUM, "aborted_sessions", "total dns sessions aborted" },
 
     { CountType::END, nullptr, nullptr }
 };
@@ -100,10 +100,31 @@ static DNSData* SetNewDNSData(Packet* p)
     return &fd->session;
 }
 
-static DNSData* get_dns_session_data(Packet* p, bool from_server, DNSData& udpSessionData)
+bool DNSData::valid_dns(const DNSHdr& dns_header) const
 {
-    DnsFlowData* fd;
+    // Check QR bit (Query/Response)
+    bool is_query = ((dns_header.flags & 0x8000) == 0);
+
+    // Check Opcode (should be 0 for standard queries)
+    uint16_t opcode = (dns_header.flags & 0x7800) >> 11;
+    if (opcode > 2) 
+        return false;
+
+    // Check for reserved bits and RCODE
+    if (dns_header.flags & 0x7800)
+        return false;
+
+    // Validate Recursion bits (RA should not be set in a query)
+    bool ra_bit = (dns_header.flags & 0x0080) != 0;
+    if (is_query && ra_bit) 
+        return false;
+
+    return true;
+}
 
+DNSData* get_dns_session_data(Packet* p, bool from_server, DNSData& udpSessionData)
+{
+    DnsFlowData* fd;
     if (p->is_udp())
     {
         if(p->dsize > MAX_UDP_PAYLOAD)
@@ -1146,6 +1167,12 @@ static void snort_dns(Packet* p, const DnsConfig* dns_config)
         bool needNextPacket = false;
         ParseDNSResponseMessage(p, dnsSessionData, needNextPacket);
 
+        if (!dnsSessionData->valid_dns(dnsSessionData->hdr))
+        {
+            dnsSessionData->flags |= DNS_FLAG_NOT_DNS;
+            return;
+        }
+
         if (!needNextPacket and dnsSessionData->has_events())
             DataBus::publish(Dns::get_pub_id(), DnsEventIds::DNS_RESPONSE_DATA, dnsSessionData->dns_events);
 
index b60d77468c19e79f9446595da01bfca9327f460b..0c8dcdc5aad440f31de74ab3e1b4c3f7583612c4 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "flow/flow.h"
 
+#include "protocols/packet.h"
 #include "pub_sub/dns_events.h"
 
 // Implementation header with definitions, datatypes and flowdata class for
@@ -204,8 +205,11 @@ struct DNSData
 
     bool publish_response() const;
     bool has_events() const;
+    bool valid_dns(const DNSHdr&) const;
 };
 
+DNSData* get_dns_session_data(snort::Packet* p, bool from_server, DNSData& udpSessionData);
+
 class DnsResponseIp
 {
 public:
index 26d5813448c3f39819e20bd3ca7655ffa09b7b43..44d57ad206fa89eaf3b17e70ebd07b9ab01b3b79 100644 (file)
@@ -48,6 +48,7 @@ struct DnsStats
     PegCount responses;
     PegCount concurrent_sessions;
     PegCount max_concurrent_sessions;
+    PegCount aborted_sessions;
 };
 
 extern const PegInfo dns_peg_names[];
index 14c893bec7860d53efb413c653505263b1d96d48..248881415611dc268185292828085d03f9c865e1 100644 (file)
 
 #include <cassert>
 
+#include "log/messages.h"
+#include "protocols/packet.h"
+
+#include "dns.h"
+#include "dns_module.h"
+
 using namespace snort;
 
 StreamSplitter::Status DnsSplitter::scan(
-    Packet*, const uint8_t* data, uint32_t len,
+    Packet* p, const uint8_t* data, uint32_t len,
     uint32_t, uint32_t* fp)
 {
     assert(len > 0);
 
+    DNSData udp_session_data;
+    bool from_server = p->is_from_server();
+    DNSData* dnsSessionData = get_dns_session_data(p, from_server, udp_session_data);
+
+    if ( dnsSessionData and ( dnsSessionData->flags & DNS_FLAG_NOT_DNS ) )
+    {
+        dnsstats.aborted_sessions++;
+        return ABORT;
+    }
+
     if ( partial )
     {
         *fp = size + *data + 1;