]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4235: stream_tcp: add reasons for drops due to trims
authorJuweria Ali Imran (jaliimra) <jaliimra@cisco.com>
Thu, 7 Mar 2024 14:22:19 +0000 (14:22 +0000)
committerSteven Baigal (sbaigal) <sbaigal@cisco.com>
Thu, 7 Mar 2024 14:22:19 +0000 (14:22 +0000)
Merge in SNORT/snort3 from ~JALIIMRA/snort3:drop_reason to master

Squashed commit of the following:

commit fb9c9dc56abfd72ddc898814680be4f356d71ee8
Author: Juweria Ali Imran <jaliimra@cisco.com>
Date:   Thu Feb 1 03:54:41 2024 -0500

    stream_tcp: add reasons for drops due to trims

src/stream/tcp/tcp_normalizer.cc
src/stream/tcp/tcp_normalizer.h
src/stream/tcp/tcp_normalizers.h
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_session.cc

index 586925ab4e31a1d09635c28da9f1cb28a545d821..7a72fa28143f418f65fce3e3737e8606f2f7d827 100644 (file)
@@ -49,11 +49,13 @@ TcpNormalizer::NormStatus TcpNormalizer::apply_normalizations(
         if ( !tns.tracker->is_segment_seq_valid(tsd) )
         {
             tcpStats.invalid_seq_num++;
+            log_drop_reason(tns, tsd, false, "normalizer", "Normalizer: Sequence number is invalid\n");
             trim_win_payload(tns, tsd);
             return NORM_BAD_SEQ;
         }
 
         // trim to fit in listener's window and mss
+        log_drop_reason(tns, tsd, false, "normalizer", "Normalizer: Trimming payload to fit window size\n");
         trim_win_payload(tns, tsd,
             (tns.tracker->r_win_base + tns.tracker->get_snd_wnd() - tns.tracker->rcv_nxt));
 
@@ -65,11 +67,14 @@ TcpNormalizer::NormStatus TcpNormalizer::apply_normalizations(
 
     if ( stream_is_inorder )
     {
+        bool inline_mode = tsd.is_nap_policy_inline();
+
         if ( get_stream_window(tns, tsd) == 0 )
         {
             if ( !data_inside_window(tns, tsd) )
             {
-                trim_win_payload(tns, tsd, 0, tsd.is_nap_policy_inline());
+                log_drop_reason(tns, tsd, inline_mode, "normalizer", "Normalizer: Data is outside the TCP Window\n");
+                trim_win_payload(tns, tsd, 0, inline_mode);
                 return NORM_TRIMMED;
             }
 
@@ -77,20 +82,26 @@ TcpNormalizer::NormStatus TcpNormalizer::apply_normalizations(
             {
                 tcpStats.zero_win_probes++;
                 set_zwp_seq(tns, seq);
-                trim_win_payload(tns, tsd, MAX_ZERO_WIN_PROBE_LEN, tsd.is_nap_policy_inline());
+                log_drop_reason(tns, tsd, inline_mode, "normalizer", 
+                "Normalizer: Maximum Zero Window Probe length supported at a time is 1 byte\n");
+                trim_win_payload(tns, tsd, MAX_ZERO_WIN_PROBE_LEN, inline_mode);
             }
         }
     }
     else if ( get_stream_window(tns, tsd) == 0 )
     {
+        bool inline_mode = tsd.is_nap_policy_inline();
+
         if ( SEQ_EQ(seq, get_zwp_seq(tns)) )
         {
             tcpStats.zero_win_probes++;
-            trim_win_payload(tns, tsd, MAX_ZERO_WIN_PROBE_LEN, tsd.is_nap_policy_inline());
+            trim_win_payload(tns, tsd, MAX_ZERO_WIN_PROBE_LEN, inline_mode);
+            log_drop_reason(tns, tsd, inline_mode, "normalizer", "Normalizer: Maximum Zero Window Probe length supported at a time is 1 byte\n");
             return NORM_TRIMMED;
         }
 
-        trim_win_payload(tns, tsd, 0, tsd.is_nap_policy_inline());
+        log_drop_reason(tns, tsd, inline_mode, "normalizer", "Normalizer: Received data during a Zero Window that is not a Zero Window Probe\n");
+        trim_win_payload(tns, tsd, 0, inline_mode);
         return NORM_TRIMMED;
     }
 
@@ -169,30 +180,58 @@ bool TcpNormalizer::packet_dropper(
 bool TcpNormalizer::trim_syn_payload(
     TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
-    if (tsd.get_len() > max)
+    uint32_t len = tsd.get_len();
+    
+    if (len > max)
+    {
+        if ( PacketTracer::is_active() && (NormMode)tns.trim_syn == NORM_MODE_ON )
+            PacketTracer::log("Normalizer: Trimming payload of SYN packet with length (%u) to a maximum value of %u\n", len, max);
+
         return trim_payload(tns, tsd, max, (NormMode)tns.trim_syn, PC_TCP_TRIM_SYN);
+    }
     return false;
 }
 
 void TcpNormalizer::trim_rst_payload(
     TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
-    if (tsd.get_len() > max)
+    uint32_t len = tsd.get_len();
+
+    if (len > max)
+    {
+        if ( PacketTracer::is_active() && (NormMode)tns.trim_rst == NORM_MODE_ON )
+            PacketTracer::log("Normalizer: Trimming payload of RST packet with length (%u) to a maximum value of %u\n", len, max);
+
         trim_payload(tns, tsd, max, (NormMode)tns.trim_rst, PC_TCP_TRIM_RST);
+    }
 }
 
 void TcpNormalizer::trim_win_payload(
     TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max, bool force)
 {
-    if (tsd.get_len() > max)
+    uint32_t len = tsd.get_len();
+
+    if (len > max)
+    {
+        if ( PacketTracer::is_active() && (force || (NormMode)tns.trim_win == NORM_MODE_ON) )
+            PacketTracer::log("Normalizer: Trimming payload with length (%u) to a maximum value of %u\n", len, max);
+
         trim_payload(tns, tsd, max, (NormMode)tns.trim_win, PC_TCP_TRIM_WIN, force);
+    }
 }
 
 void TcpNormalizer::trim_mss_payload(
     TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
-    if (tsd.get_len() > max)
+    uint32_t len = tsd.get_len();
+
+    if (len > max)
+    {
+        if ( PacketTracer::is_active() && (NormMode)tns.trim_mss == NORM_MODE_ON )
+            PacketTracer::log("Normalizer: Trimming payload with length (%u) to fit MSS size (%u)\n", len, max);
+
         trim_payload(tns, tsd, max, (NormMode)tns.trim_mss, PC_TCP_TRIM_MSS);
+    }
 }
 
 void TcpNormalizer::ecn_tracker(
@@ -476,6 +515,16 @@ void TcpNormalizer::set_zwp_seq(
     tns.zwp_seq = seq;
 }
 
+void TcpNormalizer::log_drop_reason(TcpNormalizerState& tns, const TcpSegmentDescriptor& tsd, bool force, const char *issuer, const std::string& log)
+{
+    if ( force || (NormMode)tns.trim_win == NORM_MODE_ON )
+    {
+        tsd.get_pkt()->active->set_drop_reason(issuer);
+        if (PacketTracer::is_active())
+            PacketTracer::log("%s", log.c_str());
+    }
+}
+
 uint16_t TcpNormalizer::set_urg_offset(
     TcpNormalizerState&, const tcp::TCPHdr* tcph, uint16_t dsize)
 {
index 10b119af95ef3a0e8980c5bda0b711653b6e53b3..68e6a75acf701fa40f9290124ac33c3a35ddbb60 100644 (file)
@@ -87,6 +87,7 @@ public:
     virtual int handle_repeated_syn(State&, TcpSegmentDescriptor&) = 0;
     virtual uint16_t set_urg_offset(State&, const snort::tcp::TCPHdr* tcph, uint16_t dsize);
     virtual void set_zwp_seq(State&, uint32_t seq);
+    virtual void log_drop_reason(State&, const TcpSegmentDescriptor&, bool inline_mode, const char *issuer, const std::string& log);
 
     static void reset_stats();
 
index 2715100d0ab19119c66f24258daa4ca462c008eb..eaa3190de53d2cd7823058f1d796f861be6ee6fc 100644 (file)
@@ -101,6 +101,9 @@ public:
     void set_zwp_seq(uint32_t seq)
     { return norm->set_zwp_seq(tns, seq); }
 
+    void log_drop_reason(const TcpSegmentDescriptor& tsd, bool inline_mode, const char *issuer, const std::string& log)
+    { return norm->log_drop_reason(tns, tsd , inline_mode, issuer, log); }
+
     uint16_t set_urg_offset(const snort::tcp::TCPHdr* tcph, uint16_t dsize)
     { return norm->set_urg_offset(tns, tcph, dsize); }
 
index 1c1d2a49819a41beb62df72a97c45de468860d6b..f0fdd58b1b0988b4d95c70ba742ddca3381e7c70 100644 (file)
@@ -952,6 +952,9 @@ void TcpReassembler::fallback(TcpStreamTracker& tracker, bool server_side)
 
 bool TcpReassembler::segment_within_seglist_window(TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
 {
+    if ( !trs.sos.seglist.head )
+        return true;
+    
     uint32_t start, end = (trs.sos.seglist.tail->i_seq + trs.sos.seglist.tail->i_len);
 
     if ( SEQ_LT(trs.sos.seglist_base_seq, trs.sos.seglist.head->i_seq) )
index b1773731be112365155551c0c1cf23794a4d9729..0d9bc074a8f45f1f3596a25fe783a8d4b441f1df 100644 (file)
@@ -358,10 +358,11 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
 
             if ( inline_mode || listener->normalizer.get_trim_win() == NORM_MODE_ON)
             {
-                tsd.get_pkt()->active->set_drop_reason("stream");
                 tel.set_tcp_event(EVENT_MAX_QUEUED_BYTES_EXCEEDED);
-                if (PacketTracer::is_active())
-                    PacketTracer::log("Stream: Flow exceeded the configured max byte threshold (%u)\n", tcp_config->max_queued_bytes);
+                listener->normalizer.log_drop_reason(tsd, inline_mode, "stream", 
+                "Stream: Flow exceeded the configured max byte threshold (" + std::to_string(tcp_config->max_queued_bytes) +
+                "). You may want to adjust the 'max_bytes' parameter in the NAP policy" 
+                " to a higher value, or '0' for unlimited.\n");
             }
 
             listener->normalizer.trim_win_payload(tsd, space_left, inline_mode);
@@ -394,10 +395,11 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
 
             if ( inline_mode || listener->normalizer.get_trim_win() == NORM_MODE_ON)
             {
-                tsd.get_pkt()->active->set_drop_reason("stream");
                 tel.set_tcp_event(EVENT_MAX_QUEUED_SEGS_EXCEEDED);
-                if (PacketTracer::is_active())
-                    PacketTracer::log("Stream: Flow exceeded the configured max segment threshold (%u)\n", tcp_config->max_queued_segs);
+                listener->normalizer.log_drop_reason(tsd, inline_mode, "stream",
+                "Stream: Flow exceeded the configured max segment threshold (" + std::to_string(tcp_config->max_queued_segs) + 
+                "). You may want to adjust the 'max_segments' parameter in the NAP policy" 
+                " to a higher value, or '0' for unlimited.\n");
             }
 
             listener->normalizer.trim_win_payload(tsd, 0, inline_mode);
@@ -751,7 +753,6 @@ bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
 
 void TcpSession::mark_packet_for_drop(TcpSegmentDescriptor& tsd)
 {
-
     tsd.get_listener()->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
     set_pkt_action_flag(ACTION_BAD_PKT);
 }