exceptions: add master switch config option

This allows all traffic Exception Policies to be set from one
configuration point. All exception policy options are available in IPS
mode. Bypass, pass and auto (disabled) are also available in iDS mode

Exception Policies set up individually will overwrite this setup for the
given traffic exception.

Task #5219
pull/8430/head
Juliana Fajardini 3 years ago committed by Victor Julien
parent fab3f36b8c
commit 0d9289014b

@ -16,6 +16,45 @@ simulate failures or errors and understand Suricata behavior under such conditio
Exception Policies Exception Policies
------------------ ------------------
.. _master-switch:
Master Switch
~~~~~~~~~~~~~
It is possible to set all configuration policies via what we call "master
switch". This offers a quick way to define what the engine should do in case of
traffic exceptions, while still allowing for the flexibility of indicating a
different behavior for specific exception policies your setup/environment may
have the need to.
::
# In IPS mode, the default is drop-packet/drop-flow. To fallback to old
# behavior (setting each of them individually, or ignoring all), set this
# to ignore.
# All values available for exception policies can be used, and there is one
# extra option: auto - which means drop-packet/drop-flow in IPS mode and
# ignore in IDS mode).
# Exception policy values are: drop-packet, drop-flow, reject, bypass,
# pass-packet, pass-flow, ignore (disable).
exception-policy: auto
This value will be overwritten by specific exception policies whose settings are
also defined in the yaml file.
Auto
''''
**In IPS mode**, the default behavior for all exception policies is to drop
packets and/or flows. It is possible to disable this default, by setting the
exception policies "master switch" yaml config option to ``ignore``.
**In IDS mode**, setting auto mode actually means disabling the
``master-swtich``, or ignoring the exception policies.
Specific settings
~~~~~~~~~~~~~~~~~
Exception policies are implemented for: Exception policies are implemented for:
.. list-table:: Exception Policy configuration variables .. list-table:: Exception Policy configuration variables

@ -36,6 +36,11 @@ Upgrading 6.0 to 7.0
Major changes Major changes
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
- Upgrade of PCRE1 to PCRE2. See :ref:`pcre-update-v1-to-v2` for more details. - Upgrade of PCRE1 to PCRE2. See :ref:`pcre-update-v1-to-v2` for more details.
- Introducing the :ref:`Exception Policy's Master Switch <master-switch>`. This
allows to setup a single policy for all traffic exceptions. This is a breaking
change for the default behavior in the Exception Policies: in IPS mode, if an
exception policy is not set, it will fall back to the the master switch now,
instead of being ignored. Prevent this by disabling the master switch.
Security changes Security changes
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

@ -156,7 +156,7 @@ struct AppLayerParserState_ {
FramesContainer *frames; FramesContainer *frames;
}; };
enum ExceptionPolicy g_applayerparser_error_policy = EXCEPTION_POLICY_IGNORE; enum ExceptionPolicy g_applayerparser_error_policy = EXCEPTION_POLICY_NOT_SET;
static void AppLayerConfg(void) static void AppLayerConfg(void)
{ {

@ -945,7 +945,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
SCLogDebug("Midstream not enabled, so won't pick up a session"); SCLogDebug("Midstream not enabled, so won't pick up a session");
return 0; return 0;
} }
if (!(stream_config.midstream_policy == EXCEPTION_POLICY_IGNORE || if (!(stream_config.midstream_policy == EXCEPTION_POLICY_NOT_SET ||
stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW || stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW ||
stream_config.midstream_policy == EXCEPTION_POLICY_PASS_PACKET)) { stream_config.midstream_policy == EXCEPTION_POLICY_PASS_PACKET)) {
SCLogDebug("Midstream policy not permissive, so won't pick up a session"); SCLogDebug("Midstream policy not permissive, so won't pick up a session");
@ -1118,7 +1118,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
SCLogDebug("Midstream not enabled, so won't pick up a session"); SCLogDebug("Midstream not enabled, so won't pick up a session");
return 0; return 0;
} }
if (!(stream_config.midstream_policy == EXCEPTION_POLICY_IGNORE || if (!(stream_config.midstream_policy == EXCEPTION_POLICY_NOT_SET ||
stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW || stream_config.midstream_policy == EXCEPTION_POLICY_PASS_FLOW ||
stream_config.midstream_policy == EXCEPTION_POLICY_PASS_PACKET)) { stream_config.midstream_policy == EXCEPTION_POLICY_PASS_PACKET)) {
SCLogDebug("Midstream policy not permissive, so won't pick up a session"); SCLogDebug("Midstream policy not permissive, so won't pick up a session");

@ -125,6 +125,7 @@
#include "util-device.h" #include "util-device.h"
#include "util-dpdk.h" #include "util-dpdk.h"
#include "util-ebpf.h" #include "util-ebpf.h"
#include "util-exception-policy.h"
#include "util-host-os-info.h" #include "util-host-os-info.h"
#include "util-ioctl.h" #include "util-ioctl.h"
#include "util-landlock.h" #include "util-landlock.h"
@ -2640,6 +2641,8 @@ int PostConfLoadedSetup(SCInstance *suri)
MacSetRegisterFlowStorage(); MacSetRegisterFlowStorage();
SetMasterExceptionPolicy();
LiveDeviceFinalize(); // must be after EBPF extension registration LiveDeviceFinalize(); // must be after EBPF extension registration
RunModeEngineIsIPS( RunModeEngineIsIPS(

@ -27,59 +27,101 @@
#include "stream-tcp-reassemble.h" #include "stream-tcp-reassemble.h"
#include "action-globals.h" #include "action-globals.h"
enum ExceptionPolicy g_eps_master_switch = EXCEPTION_POLICY_NOT_SET;
static const char *ExceptionPolicyEnumToString(enum ExceptionPolicy policy)
{
switch (policy) {
case EXCEPTION_POLICY_NOT_SET:
return "ignore";
case EXCEPTION_POLICY_REJECT:
return "reject";
case EXCEPTION_POLICY_BYPASS_FLOW:
return "bypass";
case EXCEPTION_POLICY_DROP_FLOW:
return "drop-flow";
case EXCEPTION_POLICY_DROP_PACKET:
return "drop-packet";
case EXCEPTION_POLICY_PASS_PACKET:
return "pass-packet";
case EXCEPTION_POLICY_PASS_FLOW:
return "pass-flow";
}
// TODO we shouldn't reach this, but if we do, better not to leave this as simply null...
return "not set";
}
void SetMasterExceptionPolicy(void)
{
g_eps_master_switch = ExceptionPolicyParse("exception-policy", true);
}
static enum ExceptionPolicy GetMasterExceptionPolicy(const char *option)
{
return g_eps_master_switch;
}
void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason) void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason)
{ {
SCLogDebug("start: pcap_cnt %" PRIu64 ", policy %u", p->pcap_cnt, policy); SCLogDebug("start: pcap_cnt %" PRIu64 ", policy %u", p->pcap_cnt, policy);
if (EngineModeIsIPS()) { switch (policy) {
switch (policy) { case EXCEPTION_POLICY_NOT_SET:
case EXCEPTION_POLICY_IGNORE: break;
break; case EXCEPTION_POLICY_REJECT:
case EXCEPTION_POLICY_REJECT: SCLogDebug("EXCEPTION_POLICY_REJECT");
SCLogDebug("EXCEPTION_POLICY_REJECT"); PacketDrop(p, ACTION_REJECT, drop_reason);
PacketDrop(p, ACTION_REJECT, drop_reason); /* fall through */
/* fall through */ case EXCEPTION_POLICY_DROP_FLOW:
case EXCEPTION_POLICY_DROP_FLOW: SCLogDebug("EXCEPTION_POLICY_DROP_FLOW");
SCLogDebug("EXCEPTION_POLICY_DROP_FLOW"); if (p->flow) {
if (p->flow) { p->flow->flags |= FLOW_ACTION_DROP;
p->flow->flags |= FLOW_ACTION_DROP; FlowSetNoPayloadInspectionFlag(p->flow);
FlowSetNoPayloadInspectionFlag(p->flow); FlowSetNoPacketInspectionFlag(p->flow);
FlowSetNoPacketInspectionFlag(p->flow); StreamTcpDisableAppLayer(p->flow);
StreamTcpDisableAppLayer(p->flow); }
} /* fall through */
/* fall through */ case EXCEPTION_POLICY_DROP_PACKET:
case EXCEPTION_POLICY_DROP_PACKET: SCLogDebug("EXCEPTION_POLICY_DROP_PACKET");
SCLogDebug("EXCEPTION_POLICY_DROP_PACKET"); DecodeSetNoPayloadInspectionFlag(p);
DecodeSetNoPayloadInspectionFlag(p); DecodeSetNoPacketInspectionFlag(p);
DecodeSetNoPacketInspectionFlag(p); PacketDrop(p, ACTION_DROP, drop_reason);
PacketDrop(p, ACTION_DROP, drop_reason); break;
break; case EXCEPTION_POLICY_BYPASS_FLOW:
case EXCEPTION_POLICY_BYPASS_FLOW: PacketBypassCallback(p);
PacketBypassCallback(p); /* fall through */
/* fall through */ case EXCEPTION_POLICY_PASS_FLOW:
case EXCEPTION_POLICY_PASS_FLOW: SCLogDebug("EXCEPTION_POLICY_PASS_FLOW");
SCLogDebug("EXCEPTION_POLICY_PASS_FLOW"); if (p->flow) {
if (p->flow) { p->flow->flags |= FLOW_ACTION_PASS;
p->flow->flags |= FLOW_ACTION_PASS; FlowSetNoPacketInspectionFlag(p->flow); // TODO util func
FlowSetNoPacketInspectionFlag(p->flow); // TODO util func }
} /* fall through */
/* fall through */ case EXCEPTION_POLICY_PASS_PACKET:
case EXCEPTION_POLICY_PASS_PACKET: SCLogDebug("EXCEPTION_POLICY_PASS_PACKET");
SCLogDebug("EXCEPTION_POLICY_PASS_PACKET"); DecodeSetNoPayloadInspectionFlag(p);
DecodeSetNoPayloadInspectionFlag(p); DecodeSetNoPacketInspectionFlag(p);
DecodeSetNoPacketInspectionFlag(p); break;
break;
}
} }
SCLogDebug("end"); SCLogDebug("end");
} }
static enum ExceptionPolicy SetIPSOption(
const char *option, const char *value_str, enum ExceptionPolicy p)
{
if (!EngineModeIsIPS()) {
SCLogConfig("%s: %s not a valid config in IDS mode. Ignoring it.)", option, value_str);
return EXCEPTION_POLICY_NOT_SET;
}
return p;
}
enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow) enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow)
{ {
enum ExceptionPolicy policy = EXCEPTION_POLICY_IGNORE; enum ExceptionPolicy policy = EXCEPTION_POLICY_NOT_SET;
const char *value_str = NULL; const char *value_str = NULL;
if ((ConfGet(option, &value_str)) == 1 && value_str != NULL) { if ((ConfGet(option, &value_str)) == 1 && value_str != NULL) {
if (strcmp(value_str, "drop-flow") == 0) { if (strcmp(value_str, "drop-flow") == 0) {
policy = EXCEPTION_POLICY_DROP_FLOW; policy = SetIPSOption(option, value_str, EXCEPTION_POLICY_DROP_FLOW);
SCLogConfig("%s: %s", option, value_str); SCLogConfig("%s: %s", option, value_str);
} else if (strcmp(value_str, "pass-flow") == 0) { } else if (strcmp(value_str, "pass-flow") == 0) {
policy = EXCEPTION_POLICY_PASS_FLOW; policy = EXCEPTION_POLICY_PASS_FLOW;
@ -88,7 +130,7 @@ enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support
policy = EXCEPTION_POLICY_BYPASS_FLOW; policy = EXCEPTION_POLICY_BYPASS_FLOW;
SCLogConfig("%s: %s", option, value_str); SCLogConfig("%s: %s", option, value_str);
} else if (strcmp(value_str, "drop-packet") == 0) { } else if (strcmp(value_str, "drop-packet") == 0) {
policy = EXCEPTION_POLICY_DROP_PACKET; policy = SetIPSOption(option, value_str, EXCEPTION_POLICY_DROP_PACKET);
SCLogConfig("%s: %s", option, value_str); SCLogConfig("%s: %s", option, value_str);
} else if (strcmp(value_str, "pass-packet") == 0) { } else if (strcmp(value_str, "pass-packet") == 0) {
policy = EXCEPTION_POLICY_PASS_PACKET; policy = EXCEPTION_POLICY_PASS_PACKET;
@ -97,7 +139,10 @@ enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support
policy = EXCEPTION_POLICY_REJECT; policy = EXCEPTION_POLICY_REJECT;
SCLogConfig("%s: %s", option, value_str); SCLogConfig("%s: %s", option, value_str);
} else if (strcmp(value_str, "ignore") == 0) { // TODO name? } else if (strcmp(value_str, "ignore") == 0) { // TODO name?
policy = EXCEPTION_POLICY_IGNORE; policy = EXCEPTION_POLICY_NOT_SET;
SCLogConfig("%s: %s", option, value_str);
} else if (strcmp(value_str, "auto") == 0) {
policy = SetIPSOption(option, value_str, EXCEPTION_POLICY_DROP_FLOW);
SCLogConfig("%s: %s", option, value_str); SCLogConfig("%s: %s", option, value_str);
} else { } else {
FatalErrorOnInit( FatalErrorOnInit(
@ -110,12 +155,29 @@ enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support
if (policy == EXCEPTION_POLICY_DROP_FLOW || policy == EXCEPTION_POLICY_PASS_FLOW || if (policy == EXCEPTION_POLICY_DROP_FLOW || policy == EXCEPTION_POLICY_PASS_FLOW ||
policy == EXCEPTION_POLICY_BYPASS_FLOW) { policy == EXCEPTION_POLICY_BYPASS_FLOW) {
SCLogWarning("flow actions not supported for %s, defaulting to \"ignore\"", option); SCLogWarning("flow actions not supported for %s, defaulting to \"ignore\"", option);
policy = EXCEPTION_POLICY_IGNORE; policy = EXCEPTION_POLICY_NOT_SET;
} }
} }
} else if (strcmp(option, "exception-policy") == 0) {
/* not enabled, we won't change the master exception policy,
for now */
SCLogWarning("'exception-policy' master switch not set, so ignoring it."
" This behavior will change in Suricata 8, so please update your"
" config. See ticket #5219 for more details.");
g_eps_master_switch = EXCEPTION_POLICY_NOT_SET;
} else { } else {
SCLogConfig("%s: ignore", option); /* Exception Policy was not defined individually */
enum ExceptionPolicy master_policy = GetMasterExceptionPolicy(option);
if (master_policy == EXCEPTION_POLICY_NOT_SET) {
SCLogConfig("%s: ignore", option);
} else {
/* If the master switch was set and the Exception Policy option was not
individually set, use the defined master Exception Policy */
const char *value = ExceptionPolicyEnumToString(master_policy);
SCLogConfig("%s: %s (defined via 'exception-policy' master switch", option, value);
policy = master_policy;
}
} }
return policy; return policy;
} }

@ -25,7 +25,7 @@
#include "decode.h" #include "decode.h"
enum ExceptionPolicy { enum ExceptionPolicy {
EXCEPTION_POLICY_IGNORE = 0, EXCEPTION_POLICY_NOT_SET = 0,
EXCEPTION_POLICY_PASS_PACKET, EXCEPTION_POLICY_PASS_PACKET,
EXCEPTION_POLICY_PASS_FLOW, EXCEPTION_POLICY_PASS_FLOW,
EXCEPTION_POLICY_BYPASS_FLOW, EXCEPTION_POLICY_BYPASS_FLOW,
@ -34,10 +34,12 @@ enum ExceptionPolicy {
EXCEPTION_POLICY_REJECT, EXCEPTION_POLICY_REJECT,
}; };
void SetMasterExceptionPolicy(void);
void ExceptionPolicyApply( void ExceptionPolicyApply(
Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason); Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason);
enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow); enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow);
extern enum ExceptionPolicy g_eps_master_switch;
#ifdef DEBUG #ifdef DEBUG
extern uint64_t g_eps_applayer_error_offset_ts; extern uint64_t g_eps_applayer_error_offset_ts;
extern uint64_t g_eps_applayer_error_offset_tc; extern uint64_t g_eps_applayer_error_offset_tc;

@ -1278,6 +1278,19 @@ legacy:
# packet. Default is 15 # packet. Default is 15
#packet-alert-max: 15 #packet-alert-max: 15
# Exception Policies
#
# Define a common behavior for all exception policies.
# In IPS mode, the default is drop-packet/drop-flow. To fallback to old
# behavior (setting each of them individually, or ignoring all), set this
# to ignore.
# All values available for exception policies can be used, and there is one
# extra option: auto - which means drop-packet/drop-flow in IPS mode and
# ignore in IDS mode).
# Exception policy values are: drop-packet, drop-flow, reject, bypass,
# pass-packet, pass-flow, ignore (disable).
exception-policy: auto
# IP Reputation # IP Reputation
#reputation-categories-file: @e_sysconfdir@iprep/categories.txt #reputation-categories-file: @e_sysconfdir@iprep/categories.txt
#default-reputation-path: @e_sysconfdir@iprep #default-reputation-path: @e_sysconfdir@iprep

Loading…
Cancel
Save