diff --git a/doc/userguide/configuration/suricata-yaml.rst b/doc/userguide/configuration/suricata-yaml.rst index 24233b2bb79e..5715fc63bf28 100644 --- a/doc/userguide/configuration/suricata-yaml.rst +++ b/doc/userguide/configuration/suricata-yaml.rst @@ -1732,21 +1732,26 @@ Encrypted traffic There is no decryption of encrypted traffic, so once the handshake is complete continued tracking of the session is of limited use. The ``encryption-handling`` -option controls the behavior after the handshake. +option in ``app-layer.protocols.tls`` and ``app-layer.protocols.ssh`` controls +the behavior after the handshake. -If ``encryption-handling`` is set to ``default`` (or if the option is not set), -Suricata will continue to track the SSL/TLS session. Inspection will be limited, -as raw ``content`` inspection will still be disabled. There is no point in doing -pattern matching on traffic known to be encrypted. Inspection for (encrypted) -Heartbleed and other protocol anomalies still happens. +If ``encryption-handling`` in TLS protocol is set to ``default`` +(or if the option is not set), Suricata will continue to track the SSL/TLS +session. Inspection will be limited, as raw ``content`` inspection will still +be disabled. There is no point in doing pattern matching on traffic known to +be encrypted. Inspection for (encrypted) Heartbleed and other protocol +anomalies still happens. -When ``encryption-handling`` is set to ``bypass``, all processing of this session is -stopped. No further parsing and inspection happens. If ``stream.bypass`` is enabled -this will lead to the flow being bypassed, either inside Suricata or by the -capture method if it supports it and is configured for it. +.. note:: The ``encryption-handling: default`` option is only available for + SSL/TLS and not for SSH protocol. -Finally, if ``encryption-handling`` is set to ``full``, Suricata will process the -flow as normal, without inspection limitations or bypass. +When ``encryption-handling`` is set to ``bypass``, all processing of this +session is stopped. No further parsing and inspection happens. This will also +lead to the flow being bypassed, either inside Suricata or by the capture method +if it supports it and is configured for it. + +Finally, if ``encryption-handling`` is set to ``full``, Suricata will process +the flow as normal, without inspection limitations or bypass. The option has replaced the ``no-reassemble`` option. If ``no-reassemble`` is present, and ``encryption-handling`` is not, ``false`` is interpreted as @@ -2074,12 +2079,12 @@ are typically provided through the command line, are contained in the node parameters. There are two ways to specify arguments: lengthy and short. Dashes are omitted when describing the arguments. This setup node can be used to set up the memory configuration, accessible NICs, and other EAL-related -parameters, among other things. The node `dpdk.eal-params` also supports -multiple arguments of the same type. This can be useful for EAL arguments -such as `--vdev`, `--allow`, or `--block`. Values for these EAL arguments -are specified as a comma-separated list. -An example of such usage can be found in the example above where the `allow` -argument only makes `0000:3b:00.0` and `0000:3b:00.1` accessible to Suricata. +parameters, among other things. The node `dpdk.eal-params` also supports +multiple arguments of the same type. This can be useful for EAL arguments +such as `--vdev`, `--allow`, or `--block`. Values for these EAL arguments +are specified as a comma-separated list. +An example of such usage can be found in the example above where the `allow` +argument only makes `0000:3b:00.0` and `0000:3b:00.1` accessible to Suricata. arguments with list node. such as --vdev, --allow, --block eal options. The definition of lcore affinity as an EAL parameter is a standard practice. However, lcore parameters like `-l`, `-c`, diff --git a/doc/userguide/performance/ignoring-traffic.rst b/doc/userguide/performance/ignoring-traffic.rst index a2c7a8825528..ddb2e86bc6b2 100644 --- a/doc/userguide/performance/ignoring-traffic.rst +++ b/doc/userguide/performance/ignoring-traffic.rst @@ -73,10 +73,14 @@ Example:: encrypted traffic ----------------- -The TLS app layer parser has the ability to stop processing encrypted traffic -after the initial handshake. By setting the `app-layer.protocols.tls.encryption-handling` -option to `bypass` the rest of this flow is ignored. If flow bypass is enabled, -the bypass is done in the kernel or in hardware. +The TLS and SSH app layer parsers have the ability to stop processing +encrypted traffic after the initial handshake. By setting the +`app-layer.protocols.tls.encryption-handling` and +`app-layer.protocols.tls.encryption-handling` options to `bypass` Suricata +bypasses flows once the handshake is completed and encrypted traffic is +detected. The rest of these flow is ignored. +The bypass is done in the kernel or in hardware, similar to how flow bypass +is done. .. _bypass: diff --git a/rust/src/ssh/ssh.rs b/rust/src/ssh/ssh.rs index a6a3871a8e60..4b1d1ffe1a0c 100644 --- a/rust/src/ssh/ssh.rs +++ b/rust/src/ssh/ssh.rs @@ -25,11 +25,16 @@ use crate::frames::Frame; static mut ALPROTO_SSH: AppProto = ALPROTO_UNKNOWN; static HASSH_ENABLED: AtomicBool = AtomicBool::new(false); +static BYPASS_ENABLED: AtomicBool = AtomicBool::new(false); fn hassh_is_enabled() -> bool { HASSH_ENABLED.load(Ordering::Relaxed) } +fn enc_bypass_is_enabled() -> bool { + BYPASS_ENABLED.load(Ordering::Relaxed) +} + #[derive(AppLayerFrameType)] pub enum SshFrameType { RecordHdr, @@ -197,11 +202,18 @@ impl SSHState { unsafe { AppLayerParserStateSetFlag( pstate, - APP_LAYER_PARSER_NO_INSPECTION - | APP_LAYER_PARSER_NO_REASSEMBLY - | APP_LAYER_PARSER_BYPASS_READY, + APP_LAYER_PARSER_NO_INSPECTION, ); } + if enc_bypass_is_enabled() { + unsafe { + AppLayerParserStateSetFlag( + pstate, + APP_LAYER_PARSER_NO_REASSEMBLY + | APP_LAYER_PARSER_BYPASS_READY, + ); + } + } } } _ => {} @@ -549,6 +561,16 @@ pub extern "C" fn rs_ssh_hassh_is_enabled() -> bool { hassh_is_enabled() } +#[no_mangle] +pub extern "C" fn rs_ssh_enable_bypass() { + BYPASS_ENABLED.store(true, Ordering::Relaxed) +} + +#[no_mangle] +pub extern "C" fn rs_ssh_enc_bypass_is_enabled() -> bool { + enc_bypass_is_enabled() +} + #[no_mangle] pub unsafe extern "C" fn rs_ssh_tx_get_log_condition( tx: *mut std::os::raw::c_void) -> bool { let tx = cast_pointer!(tx, SSHTransaction); diff --git a/src/app-layer-ssh.c b/src/app-layer-ssh.c index 71bc786ad6b4..979f4b40b038 100644 --- a/src/app-layer-ssh.c +++ b/src/app-layer-ssh.c @@ -55,6 +55,8 @@ /* HASSH fingerprints are disabled by default */ #define SSH_CONFIG_DEFAULT_HASSH false +/* Bypassing the encrypted part of the connections */ +#define SSH_CONFIG_DEFAULT_BYPASS true static int SSHRegisterPatternsForProtocolDetection(void) { @@ -103,6 +105,23 @@ void RegisterSSHParsers(void) if (RunmodeIsUnittests() || enable_hassh) { rs_ssh_enable_hassh(); } + + bool enc_bypass = SSH_CONFIG_DEFAULT_BYPASS; + ConfNode *enc_handle = ConfGetNode("app-layer.protocols.ssh.encryption-handling"); + if (enc_handle != NULL && enc_handle->val != NULL) { + if (strcmp(enc_handle->val, "full") == 0) { + enc_bypass = false; + } else if (strcmp(enc_handle->val, "bypass") == 0) { + enc_bypass = true; + } else { + enc_bypass = SSH_CONFIG_DEFAULT_BYPASS; + } + } + + if (enc_bypass) { + SCLogConfig("ssh: bypass on the start of encryption enabled"); + rs_ssh_enable_bypass(); + } } SCLogDebug("Registering Rust SSH parser."); diff --git a/src/stream-tcp.c b/src/stream-tcp.c index b212f1e99164..1ad8ffb45427 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -5651,17 +5651,13 @@ int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, } if (ssn->flags & STREAMTCP_FLAG_BYPASS) { - /* we can call bypass callback, if enabled */ - if (StreamTcpBypassEnabled()) { - PacketBypassCallback(p); - } - - /* if stream is dead and we have no detect engine at all, bypass. */ + PacketBypassCallback(p); } else if (g_detect_disabled && (ssn->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) && (ssn->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) && StreamTcpBypassEnabled()) { + /* if stream is dead and we have no detect engine at all, bypass. */ SCLogDebug("bypass as stream is dead and we have no rules"); PacketBypassCallback(p); } diff --git a/suricata.yaml.in b/suricata.yaml.in index 3e73623c4b21..7530100a2535 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -931,7 +931,14 @@ app-layer: #enabled: yes ssh: enabled: yes - #hassh: yes + # hassh: no + + # What to do when the encrypted communications start: + # - bypass: stop processing this flow as much as possible. + # Offload flow bypass to kernel or hardware if possible. + # - full: keep tracking and inspection as normal + # + # encryption-handling: bypass doh2: enabled: yes http2: