From: Ron Dempster (rdempste) Date: Wed, 30 Nov 2022 16:32:12 +0000 (+0000) Subject: Pull request #3658: Established event X-Git-Tag: 3.1.48.0~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9d8ddd978c50082ccc085fb11550f1c7e5d7dd8;p=thirdparty%2Fsnort3.git Pull request #3658: Established event Merge in SNORT/snort3 from ~RDEMPSTE/snort3:established_event to master Squashed commit of the following: commit 38c51afab570fba0dff01bfe8f334b04632b74a1 Author: Ron Dempster (rdempste) Date: Thu Oct 13 10:52:10 2022 -0400 flow, stream: added code to track and event for one-sided TCP sessions and generate an event for established or one-sided flows --- diff --git a/src/flow/flow.cc b/src/flow/flow.cc index 1e27dacb0..202770d80 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -408,6 +408,10 @@ void Flow::markup_packet_flags(Packet* p) { p->packet_flags |= PKT_STREAM_UNEST_UNI; } + if ( (ssn_state.session_flags & SSNFLAG_TCP_ONE_SIDED) == SSNFLAG_TCP_ONE_SIDED ) + { + p->packet_flags |= PKT_TCP_ONE_SIDED; + } } else { diff --git a/src/flow/flow.h b/src/flow/flow.h index 82e4edd35..f1cf13808 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -66,6 +66,8 @@ #define SSNFLAG_PRUNED 0x00002000 #define SSNFLAG_RESET 0x00004000 +#define SSNFLAG_TCP_ONE_SIDED 0x00008000 + #define SSNFLAG_DROP_CLIENT 0x00010000 #define SSNFLAG_DROP_SERVER 0x00020000 diff --git a/src/framework/data_bus.h b/src/framework/data_bus.h index 9770aa5e9..b53a0d14a 100644 --- a/src/framework/data_bus.h +++ b/src/framework/data_bus.h @@ -167,6 +167,7 @@ private: #define STREAM_TCP_SYN_EVENT "stream.tcp_syn" #define STREAM_TCP_SYN_ACK_EVENT "stream.tcp_syn_ack" #define STREAM_TCP_MIDSTREAM_EVENT "stream.tcp_midstream" +#define STREAM_TCP_ESTABLISHED_EVENT "stream.tcp_established" // A new standby flow was generated by stream high availability #define STREAM_HA_NEW_FLOW_EVENT "stream.ha.new_flow" diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index 4106a9ce0..1ed138068 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -2145,7 +2145,10 @@ void InspectorManager::internal_execute(Packet* p) else { if ( !p->has_paf_payload() and p->flow->flow_state == Flow::FlowState::INSPECT ) - p->flow->session->process(p); + { + Flow& flow = *p->flow; + flow.session->process(p); + } if ( p->flow->reload_id != reload_id ) { diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 3b8ca361c..530d18e9e 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -86,7 +86,7 @@ class SFDAQInstance; #define PKT_MORE_TO_FLUSH 0x20000000 // when more data is available to StreamSplitter::scan #define PKT_FAST_PAT_EVAL 0x40000000 // temporary until IpsOption api updated -#define PKT_UNUSED_FLAGS 0x80000000 +#define PKT_TCP_ONE_SIDED 0x80000000 // A one-sided TCP session was detected #define TS_PKT_OFFLOADED 0x01 diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 7a7010ef8..7a69e9752 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -102,6 +102,7 @@ bool TcpSession::setup(Packet*) cleaning = false; splitter_init = false; + initiator_watermark = 0; pkt_action_mask = ACTION_NOTHING; ecn = 0; ingress_index = egress_index = 0; diff --git a/src/stream/tcp/tcp_state_listen.cc b/src/stream/tcp/tcp_state_listen.cc index 39ea68ff1..26d31700f 100644 --- a/src/stream/tcp/tcp_state_listen.cc +++ b/src/stream/tcp/tcp_state_listen.cc @@ -213,3 +213,9 @@ bool TcpStateListen::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) return true; } +bool TcpStateListen::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) +{ + trk.session->check_for_one_sided_session(tsd.get_pkt()); + return true; +} + diff --git a/src/stream/tcp/tcp_state_listen.h b/src/stream/tcp/tcp_state_listen.h index 34b34422e..0575e8ff8 100644 --- a/src/stream/tcp/tcp_state_listen.h +++ b/src/stream/tcp/tcp_state_listen.h @@ -40,6 +40,8 @@ public: bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override; bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override; bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override; + + bool do_post_sm_packet_actions(TcpSegmentDescriptor&, TcpStreamTracker&) override; }; #endif diff --git a/src/stream/tcp/tcp_state_syn_recv.cc b/src/stream/tcp/tcp_state_syn_recv.cc index 499882f04..6b18e98e6 100644 --- a/src/stream/tcp/tcp_state_syn_recv.cc +++ b/src/stream/tcp/tcp_state_syn_recv.cc @@ -78,12 +78,9 @@ bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& { if ( trk.is_ack_valid(tsd.get_ack()) ) { - Flow* flow = tsd.get_flow(); - trk.update_tracker_ack_recv(tsd); trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs()); - flow->set_session_flags(SSNFLAG_ESTABLISHED); - flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED ); + trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK); trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED); trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED); if ( tsd.is_data_segment() ) @@ -105,13 +102,10 @@ bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) { if ( !tsd.is_meta_ack_packet() && trk.is_ack_valid(tsd.get_ack()) ) { - Flow* flow = tsd.get_flow(); - trk.update_tracker_ack_recv(tsd); trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd)); tsd.set_packet_flags(PKT_STREAM_TWH); - flow->set_session_flags(SSNFLAG_ESTABLISHED); - flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED ); + trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK); trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED); trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED); trk.session->check_for_window_slam(tsd); diff --git a/src/stream/tcp/tcp_state_syn_sent.cc b/src/stream/tcp/tcp_state_syn_sent.cc index e2eacf9af..7a0ce1d75 100644 --- a/src/stream/tcp/tcp_state_syn_sent.cc +++ b/src/stream/tcp/tcp_state_syn_sent.cc @@ -66,11 +66,8 @@ bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) { - Flow* flow = tsd.get_flow(); - trk.update_tracker_ack_sent(tsd); - flow->set_session_flags(SSNFLAG_ESTABLISHED); - flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED ); + trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK); trk.session->update_timestamp_tracking(tsd); trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED); trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED); @@ -86,11 +83,8 @@ bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) bool TcpStateSynSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) { - Flow* flow = tsd.get_flow(); - trk.update_tracker_ack_sent(tsd); - flow->set_session_flags(SSNFLAG_ESTABLISHED); - flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED ); + trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK); trk.session->update_timestamp_tracking(tsd); trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED); trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED); diff --git a/src/stream/tcp/tcp_stream_session.cc b/src/stream/tcp/tcp_stream_session.cc index 9a6f276cb..7824bbf78 100644 --- a/src/stream/tcp/tcp_stream_session.cc +++ b/src/stream/tcp/tcp_stream_session.cc @@ -25,6 +25,7 @@ #include "tcp_stream_session.h" +#include "framework/data_bus.h" #include "log/messages.h" #include "stream/tcp/tcp_ha.h" @@ -98,8 +99,7 @@ void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd if ( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT ) { // should TCP state go to established too? - flow->session_state |= STREAM_STATE_ESTABLISHED; - flow->set_session_flags(SSNFLAG_ESTABLISHED); + set_established(tsd.get_pkt()); update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED); } } @@ -120,10 +120,7 @@ void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd { /* Midstream and seen server. */ if ( flow->get_session_flags() & SSNFLAG_SEEN_SERVER ) - { - flow->session_state |= STREAM_STATE_ESTABLISHED; - flow->set_session_flags(SSNFLAG_ESTABLISHED); - } + set_established(tsd.get_pkt()); } if ( !flow->inner_client_ttl && !tsd.is_meta_ack_packet() ) @@ -393,3 +390,48 @@ StreamSplitter* TcpStreamSession::get_splitter(bool to_server) void TcpStreamSession::start_proxy() { tcp_config->policy = StreamPolicy::OS_PROXY; } +void TcpStreamSession::set_established(Packet* p, uint32_t flags) +{ + flow->session_state |= STREAM_STATE_ESTABLISHED | flags; + if (SSNFLAG_ESTABLISHED != (SSNFLAG_ESTABLISHED & flow->get_session_flags())) + { + flow->set_session_flags(SSNFLAG_ESTABLISHED); + DataBus::publish(STREAM_TCP_ESTABLISHED_EVENT, p); + } +} + +void TcpStreamSession::check_for_one_sided_session(Packet* p) +{ + Flow& flow = *p->flow; + if ( !( (SSNFLAG_ESTABLISHED | SSNFLAG_TCP_ONE_SIDED) & flow.ssn_state.session_flags ) + && p->is_from_client_originally() ) + { + uint64_t initiator_packets; + uint64_t responder_packets; + if (flow.flags.client_initiated) + { + initiator_packets = flow.flowstats.client_pkts; + responder_packets = flow.flowstats.server_pkts; + } + else + { + initiator_packets = flow.flowstats.server_pkts; + responder_packets = flow.flowstats.client_pkts; + } + + if ( !responder_packets ) + { + // handle case where traffic is only in one direction, but the sequence numbers + // are changing indicating an asynchronous session + uint32_t watermark = p->ptrs.tcph->seq() + p->ptrs.tcph->ack(); + if ( 1 == initiator_packets ) + initiator_watermark = watermark; + else if ( initiator_watermark != watermark ) + { + flow.ssn_state.session_flags |= SSNFLAG_TCP_ONE_SIDED; + DataBus::publish(STREAM_TCP_ESTABLISHED_EVENT, p); + } + } + } +} + diff --git a/src/stream/tcp/tcp_stream_session.h b/src/stream/tcp/tcp_stream_session.h index b6e43d2d4..8145f7b0d 100644 --- a/src/stream/tcp/tcp_stream_session.h +++ b/src/stream/tcp/tcp_stream_session.h @@ -99,6 +99,9 @@ public: void set_pkt_action_flag(uint32_t flag) { pkt_action_mask |= flag; } + void set_established(snort::Packet*, uint32_t flags = 0); + void check_for_one_sided_session(snort::Packet*); + virtual void update_paws_timestamps(TcpSegmentDescriptor&) = 0; virtual void check_for_repeated_syn(TcpSegmentDescriptor&) = 0; virtual void check_for_session_hijack(TcpSegmentDescriptor&) = 0; @@ -112,10 +115,10 @@ public: bool lws_init = false; bool tcp_init = false; uint32_t pkt_action_mask = ACTION_NOTHING; - uint8_t ecn = 0; + uint32_t initiator_watermark = 0; int32_t ingress_index = DAQ_PKTHDR_UNKNOWN; - int16_t ingress_group = DAQ_PKTHDR_UNKNOWN; int32_t egress_index = DAQ_PKTHDR_UNKNOWN; + int16_t ingress_group = DAQ_PKTHDR_UNKNOWN; int16_t egress_group = DAQ_PKTHDR_UNKNOWN; uint32_t daq_flags = 0; uint32_t address_space_id = 0; @@ -124,6 +127,7 @@ public: TcpEventLogger tel; bool cleaning = false; uint8_t held_packet_dir = SSN_DIR_NONE; + uint8_t ecn = 0; private: bool no_ack = false; diff --git a/src/stream/tcp/tcp_stream_tracker.cc b/src/stream/tcp/tcp_stream_tracker.cc index cfef5f3e1..0b6d314bc 100644 --- a/src/stream/tcp/tcp_stream_tracker.cc +++ b/src/stream/tcp/tcp_stream_tracker.cc @@ -552,13 +552,10 @@ bool TcpStreamTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd) if ( good_ack ) { - Flow* flow = tsd.get_flow(); - irs = tsd.get_seq(); finish_client_init(tsd); update_tracker_ack_recv(tsd); - flow->set_session_flags(SSNFLAG_ESTABLISHED); - flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED ); + session->set_established(tsd.get_pkt(), STREAM_STATE_ACK); tcp_state = TcpStreamTracker::TCP_ESTABLISHED; }