Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple stream bypass from TLS encrypted bypass v5 #11886

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 23 additions & 18 deletions doc/userguide/configuration/suricata-yaml.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1736,21 +1736,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
Expand Down Expand Up @@ -2078,12 +2083,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`,
Expand Down
12 changes: 8 additions & 4 deletions doc/userguide/performance/ignoring-traffic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.ssh.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:

Expand Down
11 changes: 11 additions & 0 deletions doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ Major changes
- sip.to
- sip.content_type
- sip.content_length
- Encrypted traffic bypass has been decoupled from stream.bypass setting.
This means that encrypted traffic can be bypassed while tracking/fully
inspecting other traffic as well.
- Encrypted SSH traffic bypass is now independently controlled through
`app-layer.protocols.ssh.encryption-handling` setting. The setting can either
be `bypass` or `full`, setting `default` as found in the TLS protocol is
NOT supported. To retain the previous behavior of encrypted traffic bypass
combined with stream depth bypass, set
`app-layer.protocols.ssh.encryption-handling` to `bypass` (while also
setting `app-layer.protocols.tls.encryption-handling` to `bypass` and
`stream.bypass` to `true`).

Removals
~~~~~~~~
Expand Down
28 changes: 25 additions & 3 deletions rust/src/ssh/ssh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
);
}
}
}
}
_ => {}
Expand Down Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions src/app-layer-ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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.");
Expand Down
8 changes: 2 additions & 6 deletions src/stream-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5659,17 +5659,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);
}
Expand Down
9 changes: 8 additions & 1 deletion suricata.yaml.in
Original file line number Diff line number Diff line change
Expand Up @@ -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: full
doh2:
enabled: yes
http2:
Expand Down
Loading