From: Ron Dempster (rdempste) Date: Mon, 10 Oct 2022 15:07:25 +0000 (+0000) Subject: Pull request #3615: Reputation X-Git-Tag: 3.1.45.0~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb8603d5343f3531e874b6600acdb003f03e623b;p=thirdparty%2Fsnort3.git Pull request #3615: Reputation Merge in SNORT/snort3 from ~RDEMPSTE/snort3:reputation to master Squashed commit of the following: commit 8570cbe9d6a889c4393efd885ee0365d5820fc24 Author: Ron Dempster (rdempste) Date: Mon Sep 12 14:29:20 2022 -0400 reputation: added profiling to the event handlers commit 6641fdf35ecadf53d9f7114fd54ef9e04c5f3712 Author: Ron Dempster (rdempste) Date: Fri Aug 19 16:21:26 2022 -0400 flow, reputation, protocols: remove reputation information from packet and flow commit 67b9574c7c955cd4022a94f592c326295e9e03f0 Author: Ron Dempster (rdempste) Date: Thu Aug 18 16:45:49 2022 -0400 reputation: refactor event generation for matches --- diff --git a/src/flow/flow.h b/src/flow/flow.h index d4343be59..f057c27ee 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -456,8 +456,6 @@ public: // FIXIT-M privatize if possible unsigned ips_policy_id; unsigned reload_id; - uint32_t iplist_monitor_id; - uint32_t tenant; uint32_t default_session_timeout; @@ -487,10 +485,6 @@ public: // FIXIT-M privatize if possible // currently considered to be the client bool app_direction_swapped : 1; // Packet direction swapped from application perspective bool disable_inspect : 1; - bool reputation_src_dest : 1; - bool reputation_blocklist : 1; - bool reputation_monitor : 1; - bool reputation_allowlist : 1; bool trigger_detained_packet_event : 1; bool trigger_finalize_event : 1; bool use_direct_inject : 1; diff --git a/src/network_inspectors/reputation/reputation_inspect.cc b/src/network_inspectors/reputation/reputation_inspect.cc index 9f8d1de4b..2f1a38c92 100644 --- a/src/network_inspectors/reputation/reputation_inspect.cc +++ b/src/network_inspectors/reputation/reputation_inspect.cc @@ -75,7 +75,7 @@ static inline IPrepInfo* reputation_lookup(const ReputationConfig& config, } static inline IPdecision get_reputation(const ReputationConfig& config, ReputationData& data, - IPrepInfo* rep_info, uint32_t* listid, uint32_t ingress_intf, uint32_t egress_intf) + IPrepInfo* rep_info, uint32_t& listid, uint32_t ingress_intf, uint32_t egress_intf) { IPdecision decision = DECISION_NULL; @@ -100,13 +100,13 @@ static inline IPdecision get_reputation(const ReputationConfig& config, Reputati return DECISION_NULL; if (config.priority == (IPdecision)list_info[list_index]->list_type ) { - *listid = list_info[list_index]->list_id; + listid = list_info[list_index]->list_id; return ((IPdecision)list_info[list_index]->list_type); } else if ( decision < list_info[list_index]->list_type) { decision = (IPdecision)list_info[list_index]->list_type; - *listid = list_info[list_index]->list_id; + listid = list_info[list_index]->list_id; } } } @@ -120,14 +120,14 @@ static inline IPdecision get_reputation(const ReputationConfig& config, Reputati } static bool decision_per_layer(const ReputationConfig& config, ReputationData& data, - Packet* p, uint32_t ingress_intf, uint32_t egress_intf, const ip::IpApi& ip_api, + uint32_t& iplist_id, uint32_t ingress_intf, uint32_t egress_intf, const ip::IpApi& ip_api, IPdecision* decision_final) { const SfIp* ip = ip_api.get_src(); IPrepInfo* result = reputation_lookup(config, data, ip); if (result) { - IPdecision decision = get_reputation(config, data, result, &p->iplist_id, ingress_intf, + IPdecision decision = get_reputation(config, data, result, iplist_id, ingress_intf, egress_intf); if (decision == BLOCKED) @@ -147,7 +147,7 @@ static bool decision_per_layer(const ReputationConfig& config, ReputationData& d result = reputation_lookup(config, data, ip); if (result) { - IPdecision decision = get_reputation(config, data, result, &p->iplist_id, ingress_intf, + IPdecision decision = get_reputation(config, data, result, iplist_id, ingress_intf, egress_intf); if (decision == BLOCKED) @@ -167,7 +167,7 @@ static bool decision_per_layer(const ReputationConfig& config, ReputationData& d } static IPdecision reputation_decision(const ReputationConfig& config, ReputationData& data, - Packet* p) + Packet* p, uint32_t& iplist_id) { IPdecision decision_final = DECISION_NULL; uint32_t ingress_intf = 0; @@ -184,7 +184,7 @@ static IPdecision reputation_decision(const ReputationConfig& config, Reputation if (config.nested_ip == INNER) { - decision_per_layer(config, data, p, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final); + decision_per_layer(config, data, iplist_id, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final); return decision_final; } @@ -197,7 +197,7 @@ static IPdecision reputation_decision(const ReputationConfig& config, Reputation if (config.nested_ip == OUTER) { layer::set_outer_ip_api(p, p->ptrs.ip_api, p->ip_proto_next, num_layer); - decision_per_layer(config, data, p, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final); + decision_per_layer(config, data, iplist_id, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final); } else if (config.nested_ip == ALL) { @@ -206,7 +206,7 @@ static IPdecision reputation_decision(const ReputationConfig& config, Reputation while (!done and layer::set_outer_ip_api(p, p->ptrs.ip_api, p->ip_proto_next, num_layer)) { - done = decision_per_layer(config, data, p, ingress_intf, egress_intf, p->ptrs.ip_api, + done = decision_per_layer(config, data, iplist_id, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_current); if (decision_current != DECISION_NULL) { @@ -252,19 +252,18 @@ static IPdecision snort_reputation_aux_ip(const ReputationConfig& config, Reputa IPrepInfo* result = reputation_lookup(config, data, ip); if (result) { - decision = get_reputation(config, data, result, &p->iplist_id, ingress_intf, + uint32_t iplist_id; + decision = get_reputation(config, data, result, iplist_id, ingress_intf, egress_intf); if (decision == BLOCKED) { - if (p->flow) - p->flow->flags.reputation_blocklist = true; - // Prior to IPRep logging, IPS policy must be set to the default policy, set_ips_policy(get_default_ips_policy(SnortConfig::get_conf())); DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_BLOCKLIST_DST); - DataBus::publish(REPUTATION_MATCHED_EVENT, p); + ReputationVerdictEvent event(p, REP_VERDICT_BLOCKED, iplist_id, false); + DataBus::publish(REPUTATION_MATCHED_EVENT, event); p->active->drop_packet(p, true); // disable all preproc analysis and detection for this packet @@ -282,23 +281,16 @@ static IPdecision snort_reputation_aux_ip(const ReputationConfig& config, Reputa } else if (decision == MONITORED) { - if (p->flow) - { - p->flow->flags.reputation_monitor = true; - p->flow->iplist_monitor_id = p->iplist_id; - } - DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_MONITOR_DST); - DataBus::publish(REPUTATION_MATCHED_EVENT, p); + ReputationVerdictEvent event(p, REP_VERDICT_MONITORED, iplist_id, false); + DataBus::publish(REPUTATION_MATCHED_EVENT, event); reputationstats.aux_ip_monitored++; } else if (decision == TRUSTED) { - if (p->flow) - p->flow->flags.reputation_allowlist = true; - DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_ALLOWLIST_DST); - DataBus::publish(REPUTATION_MATCHED_EVENT, p); + ReputationVerdictEvent event(p, REP_VERDICT_TRUSTED, iplist_id, false); + DataBus::publish(REPUTATION_MATCHED_EVENT, event); p->active->trust_session(p, true); reputationstats.aux_ip_trusted++; } @@ -337,7 +329,7 @@ static const char* to_string(IPdecision ipd) } } -static void populate_trace_data(IPdecision& decision, Packet* p) +static void populate_trace_data(IPdecision& decision, Packet* p, uint32_t iplist_id) { char addr[INET6_ADDRSTRLEN]; const SfIp* ip = nullptr; @@ -356,7 +348,7 @@ static void populate_trace_data(IPdecision& decision, Packet* p) PacketTracer::daq_log("SI-IP+%" PRId64"+%s list id %u+Matched ip %s, action %s$", TO_NSECS(pt_timer->get()), (TRUSTED_SRC == decision or TRUSTED_DST == decision)?"Do_not_block":"Block", - p->iplist_id, addr, to_string(decision)); + iplist_id, addr, to_string(decision)); } static void snort_reputation(const ReputationConfig& config, ReputationData& data, Packet* p) @@ -366,7 +358,8 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat if (!data.ip_list) return; - decision = reputation_decision(config, data, p); + uint32_t iplist_id; + decision = reputation_decision(config, data, p, iplist_id); Active* act = p->active; if (BLOCKED_SRC == decision or BLOCKED_DST == decision) @@ -374,26 +367,23 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat unsigned blocklist_event = (BLOCKED_SRC == decision) ? REPUTATION_EVENT_BLOCKLIST_SRC : REPUTATION_EVENT_BLOCKLIST_DST; - if (p->flow) - { - p->flow->flags.reputation_blocklist = true; - p->flow->flags.reputation_src_dest = (BLOCKED_SRC == decision); - } - DetectionEngine::queue_event(GID_REPUTATION, blocklist_event); - DataBus::publish(REPUTATION_MATCHED_EVENT, p); + ReputationVerdictEvent event(p, REP_VERDICT_BLOCKED, iplist_id, BLOCKED_SRC == decision); + DataBus::publish(REPUTATION_MATCHED_EVENT, event); act->drop_packet(p, true); // disable all preproc analysis and detection for this packet DetectionEngine::disable_all(p); act->block_session(p, true); + if (p->flow) + p->flow->set_state(Flow::FlowState::BLOCK); act->set_drop_reason("reputation"); reputationstats.blocked++; if (PacketTracer::is_active()) PacketTracer::log("Reputation: packet blocked, drop\n"); if (PacketTracer::is_daq_activated()) - populate_trace_data(decision, p); + populate_trace_data(decision, p, iplist_id); return; } @@ -418,14 +408,9 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat unsigned monitor_event = (MONITORED_SRC == decision) ? REPUTATION_EVENT_MONITOR_SRC : REPUTATION_EVENT_MONITOR_DST; - if (p->flow) - { - p->flow->flags.reputation_monitor = true; - p->flow->flags.reputation_src_dest = (MONITORED_SRC == decision); - } - DetectionEngine::queue_event(GID_REPUTATION, monitor_event); - DataBus::publish(REPUTATION_MATCHED_EVENT, p); + ReputationVerdictEvent event(p, REP_VERDICT_MONITORED, iplist_id, MONITORED_SRC == decision); + DataBus::publish(REPUTATION_MATCHED_EVENT, event); reputationstats.monitored++; } @@ -434,20 +419,15 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat unsigned allowlist_event = (TRUSTED_SRC == decision) ? REPUTATION_EVENT_ALLOWLIST_SRC : REPUTATION_EVENT_ALLOWLIST_DST; - if (p->flow) - { - p->flow->flags.reputation_allowlist = true; - p->flow->flags.reputation_src_dest = (TRUSTED_SRC == decision); - } - DetectionEngine::queue_event(GID_REPUTATION, allowlist_event); - DataBus::publish(REPUTATION_MATCHED_EVENT, p); + ReputationVerdictEvent event(p, REP_VERDICT_TRUSTED, iplist_id, TRUSTED_SRC == decision); + DataBus::publish(REPUTATION_MATCHED_EVENT, event); act->trust_session(p, true); reputationstats.trusted++; } if (PacketTracer::is_daq_activated()) - populate_trace_data(decision, p); + populate_trace_data(decision, p, iplist_id); } static const char* to_string(NestedIP nip) @@ -483,7 +463,7 @@ class IpRepHandler : public DataHandler public: explicit IpRepHandler(Reputation& inspector) : DataHandler(REPUTATION_NAME), inspector(inspector) - { } + { order = 5; } void handle(DataEvent&, Flow*) override; private: @@ -492,13 +472,12 @@ private: void IpRepHandler::handle(DataEvent& event, Flow*) { + Profile profile(reputation_perf_stats); Packet* p = const_cast(event.get_packet()); assert(p); if (!p->has_ip()) return; - Profile profile(reputation_perf_stats); - if (PacketTracer::is_daq_activated()) PacketTracer::pt_timer_start(); diff --git a/src/protocols/packet.cc b/src/protocols/packet.cc index e2fb3e2f2..f3022aeb8 100644 --- a/src/protocols/packet.cc +++ b/src/protocols/packet.cc @@ -88,7 +88,6 @@ void Packet::reset() release_helpers(); ptrs.reset(); - iplist_id = 0; user_inspection_policy_id = 0; user_ips_policy_id = 0; user_network_policy_id = 0; diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 60481652b..c605741da 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -159,7 +159,6 @@ struct SO_PUBLIC Packet Layer* layers; /* decoded encapsulations */ PseudoPacketType pseudo_type; // valid only when PKT_PSEUDO is set - uint32_t iplist_id; uint32_t user_inspection_policy_id; uint32_t user_ips_policy_id; diff --git a/src/pub_sub/reputation_events.h b/src/pub_sub/reputation_events.h index 8f2ab9ef5..52bac8a54 100644 --- a/src/pub_sub/reputation_events.h +++ b/src/pub_sub/reputation_events.h @@ -20,6 +20,46 @@ #ifndef REPUTATION_EVENTS_H #define REPUTATION_EVENTS_H +#include "framework/data_bus.h" + #define REPUTATION_MATCHED_EVENT "rep.matched" +namespace snort +{ + +enum ReputationVerdict +{ + REP_VERDICT_BLOCKED, + REP_VERDICT_TRUSTED, + REP_VERDICT_MONITORED +}; + +class ReputationVerdictEvent : public DataEvent +{ +public: + ReputationVerdictEvent(const Packet* packet, ReputationVerdict verdict, uint32_t list_id, bool source_matched) + : packet(packet), verdict(verdict), list_id(list_id), source_matched(source_matched) + { } + + const Packet* get_packet() const override + { return packet; } + + ReputationVerdict get_verdict() const + { return verdict; } + + uint32_t get_list_id() const + { return list_id; } + + bool get_source_matched() const + { return source_matched; } + +private: + const Packet* packet; + ReputationVerdict verdict; + uint32_t list_id; + bool source_matched; +}; + +} + #endif