mirror of
https://github.com/OISF/suricata.git
synced 2026-10-12 02:07:10 +00:00
quic: encryption-handling config parameters
Ticket: 8116
This commit is contained in:
committed by
Victor Julien
parent
844f6011b1
commit
7422c97bf2
@@ -76,6 +76,7 @@ Encrypted Traffic
|
||||
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.quic.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 the flow is ignored.
|
||||
|
||||
@@ -37,6 +37,12 @@ dedicated new configuration.
|
||||
Upgrading to 9.0.0
|
||||
------------------
|
||||
|
||||
Major Changes
|
||||
~~~~~~~~~~~~~
|
||||
- Encrypted quic traffic bypass is now independently controlled through
|
||||
``app-layer.protocols.quic.encryption-handling`` setting. The setting can either
|
||||
be ``bypass``, ``track-only`` or ``full``.
|
||||
|
||||
Logging Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
- The format of IKEv1 proposal attributes has been changed to handle
|
||||
|
||||
+48
-10
@@ -21,6 +21,8 @@ use super::{
|
||||
frames::{Frame, QuicTlsExtension, StreamTag},
|
||||
parser::{quic_pkt_num, QuicData, QuicHeader, QuicType},
|
||||
};
|
||||
use crate::conf::conf_get;
|
||||
use crate::ssh::ssh::SshEncryptionHandling;
|
||||
use crate::{
|
||||
applayer::{self, *},
|
||||
direction::Direction,
|
||||
@@ -35,12 +37,16 @@ use std::collections::VecDeque;
|
||||
use std::ffi::CString;
|
||||
use suricata_sys::sys::{
|
||||
AppLayerParserState, AppProto, SCAppLayerParserConfParserEnabled,
|
||||
SCAppLayerParserRegisterLogger, SCAppLayerProtoDetectConfProtoDetectionEnabled,
|
||||
SCAppLayerParserRegisterLogger, SCAppLayerParserStateSetFlag,
|
||||
SCAppLayerProtoDetectConfProtoDetectionEnabled,
|
||||
};
|
||||
use tls_parser::TlsExtensionType;
|
||||
|
||||
static mut ALPROTO_QUIC: AppProto = ALPROTO_UNKNOWN;
|
||||
|
||||
static mut ENCRYPTION_BYPASS_ENABLED: SshEncryptionHandling =
|
||||
SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY;
|
||||
|
||||
const DEFAULT_DCID_LEN: usize = 16;
|
||||
const PKT_NUM_BUF_MAX_LEN: usize = 4;
|
||||
pub(super) const QUIC_MAX_CRYPTO_FRAG_LEN: u64 = 65535;
|
||||
@@ -251,7 +257,10 @@ impl QuicState {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
fn handle_frames(&mut self, data: QuicData, header: QuicHeader, to_server: bool) {
|
||||
fn handle_frames(
|
||||
&mut self, data: QuicData, header: QuicHeader, to_server: bool,
|
||||
pstate: *mut AppLayerParserState,
|
||||
) {
|
||||
let mut sni: Option<Vec<u8>> = None;
|
||||
let mut ua: Option<Vec<u8>> = None;
|
||||
let mut ja3: Option<String> = None;
|
||||
@@ -311,9 +320,26 @@ impl QuicState {
|
||||
}
|
||||
extv.extend_from_slice(&c.extv);
|
||||
if to_server {
|
||||
self.hello_ts = true
|
||||
self.hello_ts = true;
|
||||
} else {
|
||||
self.hello_tc = true
|
||||
self.hello_tc = true;
|
||||
}
|
||||
if self.hello_tc && self.hello_ts {
|
||||
let flags = match unsafe { ENCRYPTION_BYPASS_ENABLED } {
|
||||
SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_BYPASS => {
|
||||
APP_LAYER_PARSER_NO_INSPECTION
|
||||
| APP_LAYER_PARSER_BYPASS_READY
|
||||
}
|
||||
SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY => {
|
||||
APP_LAYER_PARSER_NO_INSPECTION
|
||||
}
|
||||
_ => 0,
|
||||
};
|
||||
if flags != 0 {
|
||||
unsafe {
|
||||
SCAppLayerParserStateSetFlag(pstate, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -330,7 +356,7 @@ impl QuicState {
|
||||
self.transactions.push_back(tx);
|
||||
}
|
||||
|
||||
fn parse(&mut self, input: &[u8], to_server: bool) -> bool {
|
||||
fn parse(&mut self, input: &[u8], to_server: bool, pstate: *mut AppLayerParserState) -> bool {
|
||||
// so as to loop over multiple quic headers in one packet
|
||||
let mut buf = input;
|
||||
while !buf.is_empty() {
|
||||
@@ -415,7 +441,7 @@ impl QuicState {
|
||||
}
|
||||
match QuicData::from_bytes(framebuf, past_frag, past_fraglen) {
|
||||
Ok(data) => {
|
||||
self.handle_frames(data, header, to_server);
|
||||
self.handle_frames(data, header, to_server, pstate);
|
||||
}
|
||||
Err(_e) => {
|
||||
self.set_event_notx(QuicEvent::ErrorOnData, header, to_server);
|
||||
@@ -467,13 +493,13 @@ unsafe extern "C" fn quic_probing_parser(
|
||||
}
|
||||
|
||||
unsafe extern "C" fn quic_parse_tc(
|
||||
_flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
|
||||
_flow: *mut Flow, state: *mut std::os::raw::c_void, pstate: *mut AppLayerParserState,
|
||||
stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
|
||||
) -> AppLayerResult {
|
||||
let state = cast_pointer!(state, QuicState);
|
||||
let buf = stream_slice.as_slice();
|
||||
|
||||
if state.parse(buf, false) {
|
||||
if state.parse(buf, false, pstate) {
|
||||
return AppLayerResult::ok();
|
||||
} else {
|
||||
return AppLayerResult::err();
|
||||
@@ -481,13 +507,13 @@ unsafe extern "C" fn quic_parse_tc(
|
||||
}
|
||||
|
||||
unsafe extern "C" fn quic_parse_ts(
|
||||
_flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
|
||||
_flow: *mut Flow, state: *mut std::os::raw::c_void, pstate: *mut AppLayerParserState,
|
||||
stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
|
||||
) -> AppLayerResult {
|
||||
let state = cast_pointer!(state, QuicState);
|
||||
let buf = stream_slice.as_slice();
|
||||
|
||||
if state.parse(buf, true) {
|
||||
if state.parse(buf, true, pstate) {
|
||||
return AppLayerResult::ok();
|
||||
} else {
|
||||
return AppLayerResult::err();
|
||||
@@ -587,6 +613,18 @@ pub unsafe extern "C" fn SCRegisterQuicParser() {
|
||||
ALPROTO_QUIC = alproto;
|
||||
if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
|
||||
let _ = AppLayerRegisterParser(&parser, alproto);
|
||||
if let Some(val) = conf_get("app-layer.protocols.quic.encryption-handling") {
|
||||
let eh = match val {
|
||||
"full" => SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_FULL,
|
||||
"track-only" => SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY,
|
||||
"bypass" => SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_BYPASS,
|
||||
_ => {
|
||||
SCFatalErrorOnInit!("Unknown value {} for quic.encryption-handling.", val);
|
||||
SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY
|
||||
}
|
||||
};
|
||||
unsafe { ENCRYPTION_BYPASS_ENABLED = eh };
|
||||
}
|
||||
}
|
||||
SCLogDebug!("Rust quic parser registered.");
|
||||
SCAppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_QUIC);
|
||||
|
||||
@@ -1249,6 +1249,8 @@ app-layer:
|
||||
|
||||
quic:
|
||||
enabled: yes
|
||||
# see tls for the different values
|
||||
#encryption-handling: track-only
|
||||
|
||||
dhcp:
|
||||
enabled: yes
|
||||
|
||||
Reference in New Issue
Block a user