From: Bhagya Tholpady (bbantwal) Date: Tue, 7 Jul 2020 11:53:55 +0000 (+0000) Subject: Merge pull request #2278 in SNORT/snort3 from ~SELYSENK/snort3:daq_trace_filtering... X-Git-Tag: 3.0.2-2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38c3487fef1bcee01b54a5630fa177a2e12f6c56;p=thirdparty%2Fsnort3.git Merge pull request #2278 in SNORT/snort3 from ~SELYSENK/snort3:daq_trace_filtering to master Squashed commit of the following: commit 4d5212770eeb623de52709d2e915e7a17d0d4aff Author: Serhii Lysenko Date: Wed Jun 17 07:35:46 2020 -0400 trace: add support for DAQ trace filtering Skip constraints check and print trace messages when DAQ sets DAQ_PKT_FLAG_DEBUG_ENABLED flag on a packet. trace.constraints.match can be set to false to ignore traces for packets without DAQ_PKT_FLAG_DEBUG_ENABLED flag. --- diff --git a/doc/trace.txt b/doc/trace.txt index e5443d59d..0e6ae9b96 100644 --- a/doc/trace.txt +++ b/doc/trace.txt @@ -112,6 +112,7 @@ Available constraints options: src_port - match all packets with a flow that has this source port dst_ip - match all packets with a flow that has this server IP address (passed as a string) dst_port - match all packets with a flow that has this destination port + match - boolean flag to enable/disable whether constraints will ever match (enabled by default) The following lines placed in snort.lua will enable all trace messages for detection filtered by ip_proto, dst_ip, src_port and dst_port: @@ -131,6 +132,24 @@ detection filtered by ip_proto, dst_ip, src_port and dst_port: } } +To create constraints that will never successfully match, set the *match* +parameter to 'false'. This is useful for situations where one is relying on +external packet filtering from the DAQ module, or for preventing all trace +messages in the context of a packet. The following is an example of such +configuration: + + trace = + { + modules = + { + snort = { all = 1 } + }, + constraints = + { + match = false + } + } + ==== Trace module - configuring trace output method There is a capability to configure the output method for trace messages. diff --git a/src/framework/packet_constraints.cc b/src/framework/packet_constraints.cc index 757f60ed7..418eb49eb 100644 --- a/src/framework/packet_constraints.cc +++ b/src/framework/packet_constraints.cc @@ -29,8 +29,9 @@ namespace { -inline bool match(const snort::PacketConstraints& cs, const snort::SfIp& sip, - const snort::SfIp& dip, uint16_t sport, uint16_t dport) +inline bool match_constraints(const snort::PacketConstraints& cs, + const snort::SfIp& sip, const snort::SfIp& dip, uint16_t sport, + uint16_t dport) { using SetBits = snort::PacketConstraints::SetBits; @@ -56,6 +57,9 @@ bool PacketConstraints::operator==(const PacketConstraints& other) const bool PacketConstraints::packet_match(const Packet& p) const { + if ( !match ) + return false; + if ( !p.has_ip() ) return false; @@ -67,16 +71,21 @@ bool PacketConstraints::packet_match(const Packet& p) const const auto sp = p.ptrs.sp; const auto dp = p.ptrs.dp; - return match(*this, sip, dip, sp, dp) or match(*this, dip, sip, dp, sp); + return match_constraints(*this, sip, dip, sp, dp) or + match_constraints(*this, dip, sip, dp, sp); } bool PacketConstraints::flow_match(const Flow& f) const { + if ( !match ) + return false; + if ( (set_bits & SetBits::IP_PROTO) and (IpProtocol(f.ip_proto) != ip_proto) ) return false; - return match(*this, f.client_ip, f.server_ip, f.client_port, f.server_port); + return match_constraints(*this, f.client_ip, f.server_ip, f.client_port, + f.server_port); } #ifdef UNIT_TEST @@ -109,7 +118,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_ip = sip; cs.dst_ip = dip; - CHECK( match(cs, sip, dip, sport, dport) ); + CHECK( match_constraints(cs, sip, dip, sport, dport) ); } SECTION("backwards") @@ -126,7 +135,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_ip = sip; cs.dst_ip = dip; - CHECK( !match(cs, dip, sip, dport, sport) ); + CHECK( !match_constraints(cs, dip, sip, dport, sport) ); } SECTION("any ip") @@ -139,7 +148,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_port = sport; cs.dst_port = dport; - CHECK( match(cs, sip, dip, sport, dport) ); + CHECK( match_constraints(cs, sip, dip, sport, dport) ); } SECTION("any port") @@ -152,7 +161,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_ip = sip; cs.dst_ip = dip; - CHECK( match(cs, sip, dip, sport, dport) ); + CHECK( match_constraints(cs, sip, dip, sport, dport) ); } SECTION("any src") @@ -165,9 +174,8 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.dst_port = dport; cs.dst_ip = dip; - CHECK( match(cs, sip, dip, sport, dport) ); + CHECK( match_constraints(cs, sip, dip, sport, dport) ); } - } #endif diff --git a/src/framework/packet_constraints.h b/src/framework/packet_constraints.h index e25073b13..08b16a37d 100644 --- a/src/framework/packet_constraints.h +++ b/src/framework/packet_constraints.h @@ -51,6 +51,8 @@ struct PacketConstraints snort::SfIp dst_ip; uint8_t set_bits = 0; + + bool match = true; }; } // namespace snort diff --git a/src/trace/dev_notes.txt b/src/trace/dev_notes.txt index 97d9ffcb2..4138096d6 100644 --- a/src/trace/dev_notes.txt +++ b/src/trace/dev_notes.txt @@ -87,3 +87,10 @@ This directory contains the trace logger framework. To create specific TraceLogger/TraceLoggerFactory pair just inherit base classes placed into "trace_log_base.h" and init TraceConfig with a new factory during configuration. +* Disabling packet constraints matching + + Constraints matching can be disabled by setting "trace.constraints.match = false" during + configuration. This is effectively saying all packets don't pass the trace filter. It may be + useful in case of using external packet filtering, such as filtering by the DAQ, or to block + printing for all trace messages in the context of a packet. + diff --git a/src/trace/trace_api.cc b/src/trace/trace_api.cc index 4cc2b8e1c..4a8da6d03 100644 --- a/src/trace/trace_api.cc +++ b/src/trace/trace_api.cc @@ -82,14 +82,20 @@ void TraceApi::log(const char* log_msg, const char* name, void TraceApi::filter(const Packet& p) { - if ( !g_packet_constraints ) + + if ( p.pkth->flags & DAQ_PKT_FLAG_DEBUG_ENABLED ) p.filtering_state.set_matched(g_constraints_generation, true); else { - const bool matched = p.flow + bool matched; + if ( !g_packet_constraints ) + matched = true; + else + { + matched = p.flow ? g_packet_constraints->flow_match(*p.flow) : g_packet_constraints->packet_match(p); - + } p.filtering_state.set_matched(g_constraints_generation, matched); } diff --git a/src/trace/trace_module.cc b/src/trace/trace_module.cc index 0966b91e4..abe6feb38 100644 --- a/src/trace/trace_module.cc +++ b/src/trace/trace_module.cc @@ -25,6 +25,7 @@ #include +#include "framework/packet_constraints.h" #include "main/snort_config.h" #include "managers/module_manager.h" @@ -102,6 +103,9 @@ void TraceModule::generate_params() { "dst_port", Parameter::PT_INT, "0:65535", nullptr, "destination port filter" }, + { "match", Parameter::PT_BOOL, nullptr, "true", + "use constraints to filter traces" }, + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -191,6 +195,8 @@ bool TraceModule::end(const char* fqn, int, SnortConfig* sc) openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON); } + trace_parser->finalize_constraints(); + delete trace_parser; trace_parser = nullptr; } diff --git a/src/trace/trace_parser.cc b/src/trace/trace_parser.cc index 696ecd43c..8d7593f3a 100644 --- a/src/trace/trace_parser.cc +++ b/src/trace/trace_parser.cc @@ -24,7 +24,6 @@ #include "trace_parser.h" #include "framework/module.h" -#include "framework/packet_constraints.h" #include "managers/module_manager.h" #include "trace_config.h" @@ -71,48 +70,51 @@ bool TraceParser::set_traces(const std::string& module_name, const Value& val) bool TraceParser::set_constraints(const Value& val) { - if ( !trace_config->constraints ) - trace_config->constraints = new PacketConstraints; - - auto& cs = *trace_config->constraints; - if ( val.is("ip_proto") ) { - cs.ip_proto = static_cast(val.get_uint8()); - cs.set_bits |= PacketConstraints::SetBits::IP_PROTO; + parsed_constraints.ip_proto = static_cast(val.get_uint8()); + parsed_constraints.set_bits |= PacketConstraints::SetBits::IP_PROTO; } else if ( val.is("src_port") ) { - cs.src_port = val.get_uint16(); - cs.set_bits |= PacketConstraints::SetBits::SRC_PORT; + parsed_constraints.src_port = val.get_uint16(); + parsed_constraints.set_bits |= PacketConstraints::SetBits::SRC_PORT; } else if ( val.is("dst_port") ) { - cs.dst_port = val.get_uint16(); - cs.set_bits |= PacketConstraints::SetBits::DST_PORT; + parsed_constraints.dst_port = val.get_uint16(); + parsed_constraints.set_bits |= PacketConstraints::SetBits::DST_PORT; } else if ( val.is("src_ip") ) { const char* str = val.get_string(); - if ( cs.src_ip.set(str) != SFIP_SUCCESS ) + if ( parsed_constraints.src_ip.set(str) != SFIP_SUCCESS ) return false; - cs.set_bits |= PacketConstraints::SetBits::SRC_IP; + parsed_constraints.set_bits |= PacketConstraints::SetBits::SRC_IP; } else if ( val.is("dst_ip") ) { const char* str = val.get_string(); - if ( cs.dst_ip.set(str) != SFIP_SUCCESS ) + if ( parsed_constraints.dst_ip.set(str) != SFIP_SUCCESS ) return false; - cs.set_bits |= PacketConstraints::SetBits::DST_IP; + parsed_constraints.set_bits |= PacketConstraints::SetBits::DST_IP; } + else if ( val.is("match") ) + parsed_constraints.match = val.get_bool(); else return false; return true; } +void TraceParser::finalize_constraints() +{ + if ( !parsed_constraints.match or parsed_constraints.set_bits ) + trace_config->constraints = new PacketConstraints(parsed_constraints); +} + void TraceParser::clear_traces() { trace_config->clear_traces(); } diff --git a/src/trace/trace_parser.h b/src/trace/trace_parser.h index e9a26a9f7..f96a5c1d5 100644 --- a/src/trace/trace_parser.h +++ b/src/trace/trace_parser.h @@ -23,6 +23,8 @@ #include #include +#include "framework/packet_constraints.h" + namespace snort { class Module; @@ -39,6 +41,7 @@ public: bool set_traces(const std::string& module_name, const snort::Value& val); bool set_constraints(const snort::Value& val); + void finalize_constraints(); void clear_traces(); void clear_constraints(); @@ -52,6 +55,7 @@ private: private: TraceConfig* trace_config = nullptr; + snort::PacketConstraints parsed_constraints; static std::map> s_configured_trace_options; }; diff --git a/src/trace/trace_swap.cc b/src/trace/trace_swap.cc index bc2eb778a..cc9341485 100644 --- a/src/trace/trace_swap.cc +++ b/src/trace/trace_swap.cc @@ -26,6 +26,7 @@ #include #include "framework/module.h" +#include "framework/packet_constraints.h" #include "log/messages.h" #include "main/analyzer_command.h" #include "main/snort_config.h" @@ -162,24 +163,24 @@ static int set(lua_State* L) lua_pushnil(L); while ( lua_next(L, 1) ) { - const char* root_tbl_name = luaL_checkstring(L, -2); - const Parameter* root_tbl_param = Parameter::find(params_tree, root_tbl_name); + const char* root_element_key = luaL_checkstring(L, -2); + const Parameter* root_parameter = Parameter::find(params_tree, root_element_key); - if ( !lua_istable(L, -1) or !root_tbl_param ) + if ( !lua_istable(L, -1) or !root_parameter ) { - LogMessage("== invalid table is provided: %s\n", root_tbl_name); + LogMessage("== invalid table is provided: %s\n", root_element_key); parse_err = true; lua_pop(L, 1); continue; } // "modules" table traversal - if ( !strcmp(root_tbl_name, params_tree[0].name) ) + else if ( !strcmp(root_element_key, params_tree[0].name) ) { set_traces = true; trace_parser.clear_traces(); - const Parameter* modules_param = (const Parameter*)root_tbl_param->range; + const Parameter* modules_param = (const Parameter*)root_parameter->range; int modules_tbl_idx = lua_gettop(L); lua_pushnil(L); @@ -190,7 +191,7 @@ static int set(lua_State* L) if ( !lua_istable(L, -1) or !module_param ) { - LogMessage("== invalid table is provided: %s.%s\n", root_tbl_name, + LogMessage("== invalid table is provided: %s.%s\n", root_element_key, module_name); parse_err = true; @@ -219,7 +220,7 @@ static int set(lua_State* L) !trace_parser.set_traces(module_name, val) ) { LogMessage("== invalid trace value is provided: %s.%s.%s = %s\n", - root_tbl_name, module_name, val_name, val.get_as_string()); + root_element_key, module_name, val_name, val.get_as_string()); parse_err = true; } @@ -231,12 +232,12 @@ static int set(lua_State* L) } } // "constraints" table traversal - else if ( !strcmp(root_tbl_name, params_tree[1].name) ) + else if ( !strcmp(root_element_key, params_tree[1].name) ) { set_constraints = true; trace_parser.clear_constraints(); - const Parameter* constraints_param = (const Parameter*)root_tbl_param->range; + const Parameter* constraints_param = (const Parameter*)root_parameter->range; int constraints_tbl_idx = lua_gettop(L); lua_pushnil(L); @@ -249,6 +250,8 @@ static int set(lua_State* L) if ( lua_isnumber(L, -1) ) val.set((double)lua_tointeger(L, -1)); + else if ( lua_isboolean(L, -1) ) + val.set(bool(lua_toboolean(L, -1))); else val.set(luaL_checkstring(L, -1)); @@ -256,7 +259,7 @@ static int set(lua_State* L) !trace_parser.set_constraints(val) ) { LogMessage("== invalid constraints value is provided: %s.%s = %s\n", - root_tbl_name, val_name, val.get_as_string()); + root_element_key, val_name, val.get_as_string()); parse_err = true; } @@ -276,6 +279,9 @@ static int set(lua_State* L) trace_parser.clear_constraints(); } + if ( set_constraints ) + trace_parser.finalize_constraints(); + main_broadcast_command(new TraceSwap( trace_parser.get_trace_config(), set_traces, set_constraints), true); @@ -290,7 +296,7 @@ static int clear(lua_State*) { // Create an empty overlay TraceConfig // It will be set in a SnortConfig during TraceSwap execution and owned by it after - main_broadcast_command(new TraceSwap(new TraceConfig()), true); + main_broadcast_command(new TraceSwap(new TraceConfig), true); return 0; }