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

Quic Support #32

Merged
merged 64 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
3fb33e2
Add quic support
bokeefe123 Jun 3, 2024
78c30ab
Update main.rs
bokeefe123 Jun 3, 2024
0937f97
fix indexing errors
bokeefe123 Jun 3, 2024
a78fe9b
probe indexing change
bokeefe123 Jun 3, 2024
567810c
configs
bokeefe123 Jun 3, 2024
1e157a4
fix usize error
bokeefe123 Jun 3, 2024
93a328b
further usize fixes
bokeefe123 Jun 3, 2024
3805488
another index fix
bokeefe123 Jun 3, 2024
94ae984
return configs
bokeefe123 Jun 3, 2024
f93a2fa
minimal performance improvements
bokeefe123 Jun 3, 2024
278a9a2
config changes
bokeefe123 Jun 3, 2024
d44ccc1
rename file
bokeefe123 Jun 3, 2024
9d42f86
lazy load bytes
bokeefe123 Jun 3, 2024
13ddd94
lazy string copy
bokeefe123 Jun 3, 2024
dff394f
other string conversion
bokeefe123 Jun 3, 2024
fa65bfe
small change again
bokeefe123 Jun 3, 2024
299330e
renove config changes
bokeefe123 Jun 3, 2024
2fdad81
rename quic stream
bokeefe123 Jun 4, 2024
af08215
parseresult done
bokeefe123 Jun 4, 2024
2646699
revert parse result
bokeefe123 Jun 4, 2024
e1e0ebf
remove configs
bokeefe123 Jun 4, 2024
e1a4291
this is gonna break a lot
bokeefe123 Jun 4, 2024
403e7cb
config changes
bokeefe123 Jun 4, 2024
b96a56c
fix reference errors
bokeefe123 Jun 4, 2024
2b2920e
import fixes
bokeefe123 Jun 4, 2024
68dee63
pub header
bokeefe123 Jun 4, 2024
d739253
public vec_u8
bokeefe123 Jun 4, 2024
f147816
import hell
bokeefe123 Jun 4, 2024
99e68e7
rename
bokeefe123 Jun 4, 2024
e9a32ad
slight fixes
bokeefe123 Jun 4, 2024
38151a2
everything mutable
bokeefe123 Jun 4, 2024
b284eb1
this wont work
bokeefe123 Jun 4, 2024
f39ec41
better cloning
bokeefe123 Jun 4, 2024
039ff3e
cloning
bokeefe123 Jun 4, 2024
8bbcec2
fix
bokeefe123 Jun 4, 2024
2be48eb
fully clone
bokeefe123 Jun 4, 2024
b9d0bac
more cloning
bokeefe123 Jun 4, 2024
89f9d8d
copy trait
bokeefe123 Jun 4, 2024
4439663
partial move
bokeefe123 Jun 4, 2024
79fd5f1
remove ref
bokeefe123 Jun 4, 2024
396535e
fix
bokeefe123 Jun 4, 2024
8b1eee2
println debugging
bokeefe123 Jun 4, 2024
197419a
fix
bokeefe123 Jun 4, 2024
a740ba1
more prints
bokeefe123 Jun 4, 2024
6f64879
hashset
bokeefe123 Jun 4, 2024
3ffa487
from clone
bokeefe123 Jun 4, 2024
b496fd1
y not
bokeefe123 Jun 4, 2024
4d10537
cleanliness
bokeefe123 Jun 4, 2024
9576f8a
print quic clone
bokeefe123 Jun 4, 2024
48f07d2
done
bokeefe123 Jun 4, 2024
a42f1c1
remove prints
bokeefe123 Jun 4, 2024
7af2643
clear on end
bokeefe123 Jun 4, 2024
0249f89
remove dead code
bokeefe123 Jun 4, 2024
b802c31
remove imports
bokeefe123 Jun 4, 2024
acea75e
remove configs
bokeefe123 Jun 4, 2024
a62d937
reference based conn_ids
bokeefe123 Jun 4, 2024
46dd3bf
configs
bokeefe123 Jun 4, 2024
d5c71b3
rename quic to quicpacket
bokeefe123 Jun 4, 2024
fab9be0
remove quic.toml
bokeefe123 Jun 4, 2024
6cde18e
remove configs
bokeefe123 Jun 4, 2024
c024d69
revert
bokeefe123 Jun 4, 2024
ec6c26b
remove configs
bokeefe123 Jun 4, 2024
ff3eb92
clippy fix
bokeefe123 Jun 5, 2024
2be6f4e
Merge pull request #11 from bokeefe123/quic-pr-clippy-
bokeefe123 Jun 6, 2024
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"examples/log_http",
"examples/log_dns",
"examples/log_tls",
"examples/log_quic",
"examples/pcap_dump",
"examples/spin",
"examples/video",
Expand Down
4 changes: 4 additions & 0 deletions core/src/filter/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ lazy_static! {
let http = g.add_node(protocol!("http"));
let ssh = g.add_node(protocol!("ssh"));
let dns = g.add_node(protocol!("dns"));
let quic = g.add_node(protocol!("quic"));
// define valid outer layers for each protocol header
g.extend_with_edges([
(ipv4, ethernet),
Expand All @@ -34,6 +35,7 @@ lazy_static! {
(http, tcp),
(ssh, tcp),
(dns, udp), (dns, tcp),
(quic, udp), //TODO: tls over quic
]);
g
};
Expand Down Expand Up @@ -250,6 +252,8 @@ mod tests {
assert!(!has_path(&protocol!("ipv4"), &protocol!("ipv4")));
assert!(!has_path(&protocol!("http"), &protocol!("udp")));
assert!(!has_path(&protocol!("tls"), &protocol!("ssh")));
assert!(has_path(&protocol!("quic"), &protocol!("udp")));
assert!(!has_path(&protocol!("quic"), &protocol!("dns")));
}

#[test]
Expand Down
11 changes: 11 additions & 0 deletions core/src/protocols/stream/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

pub mod dns;
pub mod http;
pub mod quic;
pub mod tls;

use self::dns::{parser::DnsParser, Dns};
use self::http::{parser::HttpParser, Http};
use self::quic::{parser::QuicParser, QuicPacket};
use self::tls::{parser::TlsParser, Tls};
use crate::conntrack::conn::conn_info::ConnState;
use crate::conntrack::conn_id::FiveTuple;
Expand Down Expand Up @@ -193,6 +195,7 @@ pub enum SessionData {
Tls(Box<Tls>),
Dns(Box<Dns>),
Http(Box<Http>),
Quic(Box<QuicPacket>),
Null,
}

Expand Down Expand Up @@ -235,6 +238,7 @@ pub enum ConnParser {
Tls(TlsParser),
Dns(DnsParser),
Http(HttpParser),
Quic(QuicParser),
Unknown,
}

Expand All @@ -245,6 +249,7 @@ impl ConnParser {
ConnParser::Tls(_) => ConnParser::Tls(TlsParser::default()),
ConnParser::Dns(_) => ConnParser::Dns(DnsParser::default()),
ConnParser::Http(_) => ConnParser::Http(HttpParser::default()),
ConnParser::Quic(_) => ConnParser::Quic(QuicParser::default()),
ConnParser::Unknown => ConnParser::Unknown,
}
}
Expand All @@ -255,6 +260,7 @@ impl ConnParser {
ConnParser::Tls(parser) => parser.parse(pdu),
ConnParser::Dns(parser) => parser.parse(pdu),
ConnParser::Http(parser) => parser.parse(pdu),
ConnParser::Quic(parser) => parser.parse(pdu),
ConnParser::Unknown => ParseResult::Skipped,
}
}
Expand All @@ -265,6 +271,7 @@ impl ConnParser {
ConnParser::Tls(parser) => parser.probe(pdu),
ConnParser::Dns(parser) => parser.probe(pdu),
ConnParser::Http(parser) => parser.probe(pdu),
ConnParser::Quic(parser) => parser.probe(pdu),
ConnParser::Unknown => ProbeResult::Error,
}
}
Expand All @@ -276,6 +283,7 @@ impl ConnParser {
ConnParser::Tls(parser) => parser.remove_session(session_id),
ConnParser::Dns(parser) => parser.remove_session(session_id),
ConnParser::Http(parser) => parser.remove_session(session_id),
ConnParser::Quic(parser) => parser.remove_session(session_id),
ConnParser::Unknown => None,
}
}
Expand All @@ -286,6 +294,7 @@ impl ConnParser {
ConnParser::Tls(parser) => parser.drain_sessions(),
ConnParser::Dns(parser) => parser.drain_sessions(),
ConnParser::Http(parser) => parser.drain_sessions(),
ConnParser::Quic(parser) => parser.drain_sessions(),
ConnParser::Unknown => vec![],
}
}
Expand All @@ -296,6 +305,7 @@ impl ConnParser {
ConnParser::Tls(parser) => parser.session_match_state(),
ConnParser::Dns(parser) => parser.session_match_state(),
ConnParser::Http(parser) => parser.session_match_state(),
ConnParser::Quic(parser) => parser.session_match_state(),
ConnParser::Unknown => ConnState::Remove,
}
}
Expand All @@ -306,6 +316,7 @@ impl ConnParser {
ConnParser::Tls(parser) => parser.session_nomatch_state(),
ConnParser::Dns(parser) => parser.session_nomatch_state(),
ConnParser::Http(parser) => parser.session_nomatch_state(),
ConnParser::Quic(parser) => parser.session_nomatch_state(),
ConnParser::Unknown => ConnState::Remove,
}
}
Expand Down
24 changes: 24 additions & 0 deletions core/src/protocols/stream/quic/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Quic header types

use serde::Serialize;

/// Quic Long Header
#[derive(Debug, Serialize, Clone)]
pub struct QuicLongHeader {
pub packet_type: u8,
pub type_specific: u8,
pub version: u32,
pub dcid_len: u8, // length of dcid in bytes
pub dcid: String, // hex string
pub scid_len: u8, // length of scid in bytes
pub scid: String, // hex string
}

/// Quic Short Header
#[derive(Debug, Serialize, Clone)]
pub struct QuicShortHeader {
pub dcid: Option<String>, // optional. If not pre-existing cid then none.

#[serde(skip)]
pub dcid_bytes: Vec<u8>,
}
108 changes: 108 additions & 0 deletions core/src/protocols/stream/quic/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//! QUIC protocol parser.
//!
//! ## Remarks
//! [QUIC-INVARIANTS] https://datatracker.ietf.org/doc/rfc8999/
//! [QUIC-RFC9000] https://datatracker.ietf.org/doc/rfc9000/ (Quic V1)
//! Retina currently only parses Quic Long and Short Headers and does not attempt to parse TLS or HTTP/3 out of
//! Quic packets. The Quic protocol parser makes several assumptions about the way that quic
//! packets will behave:
//! - Assume that the Quic version is one as listed in the QuicVersion Enum in the quic/parser.rs file
//! - Assume that the dcid of a short header is a maximum of 20 bytes.
//! - Assume that the packet will not try to grease the fixed bit.
//! [QUIC-GREASE](https://www.rfc-editor.org/rfc/rfc9287.html)
//!
//! Additionally, there are a couple decisions made in the design of the quic parser:
//! - The parser will not parse a short header dcid if it is not a part of a pre-identified connection
//! - The payload bytes count is a lazy counter which does not try to exclude tokens for encryption,
//! which is a process that happens in wireshark.
/*
TODO: support parsing the tls out of the initial quic packet setup
TODO support dns over quic
TODO: support HTTP/3
*/
pub(crate) mod parser;

pub use self::header::{QuicLongHeader, QuicShortHeader};
use serde::Serialize;
pub(crate) mod header;

/// Parsed Quic Packet contents
#[derive(Debug, Serialize, Clone)]
pub struct QuicPacket {
/// Quic Short header
pub short_header: Option<QuicShortHeader>,

/// Quic Long header
pub long_header: Option<QuicLongHeader>,

/// The number of bytes contained in the estimated payload
pub payload_bytes_count: u16,
}

impl QuicPacket {
/// Returns the header type of the Quic packet (ie. "long" or "short")
pub fn header_type(&self) -> &str {
match &self.long_header {
Some(_) => "long",
None => match &self.short_header {
Some(_) => "short",
None => "",
},
}
}

/// Returns the packet type of the Quic packet
pub fn packet_type(&self) -> u8 {
match &self.long_header {
Some(long_header) => long_header.packet_type,
None => 0,
}
}

/// Returns the version of the Quic packet
pub fn version(&self) -> u32 {
match &self.long_header {
Some(long_header) => long_header.version,
None => 0,
}
}

/// Returns the destination connection ID of the Quic packet or an empty string if it does not exist
pub fn dcid(&self) -> &str {
match &self.long_header {
Some(long_header) => {
if long_header.dcid_len > 0 {
&long_header.dcid
} else {
""
}
}
None => {
if let Some(short_header) = &self.short_header {
short_header.dcid.as_deref().unwrap_or("")
} else {
""
}
}
}
}

/// Returns the source connection ID of the Quic packet or an empty string if it does not exist
pub fn scid(&self) -> &str {
match &self.long_header {
Some(long_header) => {
if long_header.scid_len > 0 {
&long_header.scid
} else {
""
}
}
None => "",
}
}

/// Returns the number of bytes in the payload of the Quic packet
pub fn payload_bytes_count(&self) -> u16 {
self.payload_bytes_count
}
}
Loading
Loading