diff --git a/rust/ja4/src/snapshots/ja4__insta@gre-erspan-vxlan.pcap.snap b/rust/ja4/src/snapshots/ja4__insta@gre-erspan-vxlan.pcap.snap index 7b74aad..b12c094 100644 --- a/rust/ja4/src/snapshots/ja4__insta@gre-erspan-vxlan.pcap.snap +++ b/rust/ja4/src/snapshots/ja4__insta@gre-erspan-vxlan.pcap.snap @@ -8,7 +8,6 @@ expression: output dst: 10.16.27.131 src_port: 65174 dst_port: 80 - ja4t: 8192__0_0 + ja4t: 8192_00_00_00 ja4l_c: 953_64 ja4l_s: 997_64 - diff --git a/rust/ja4/src/snapshots/ja4__insta@gre-sample.pcap.snap b/rust/ja4/src/snapshots/ja4__insta@gre-sample.pcap.snap index cb111bd..f690e95 100644 --- a/rust/ja4/src/snapshots/ja4__insta@gre-sample.pcap.snap +++ b/rust/ja4/src/snapshots/ja4__insta@gre-sample.pcap.snap @@ -8,7 +8,7 @@ expression: output dst: 172.28.2.3 src_port: 40264 dst_port: 22 - ja4t: 5744_2-4-8-1-3_1436_0 + ja4t: 5744_2-4-8-1-3_1436_00 ja4l_c: 36_255 ja4l_s: 22952_236 ja4ssh: diff --git a/rust/ja4/src/snapshots/ja4__insta@sshv1.pcap.snap b/rust/ja4/src/snapshots/ja4__insta@sshv1.pcap.snap index cf446b9..97070ef 100644 --- a/rust/ja4/src/snapshots/ja4__insta@sshv1.pcap.snap +++ b/rust/ja4/src/snapshots/ja4__insta@sshv1.pcap.snap @@ -8,7 +8,7 @@ expression: output dst: 3ffe:501:410:0:2c0:dfff:fe47:33e src_port: 1022 dst_port: 22 - ja4t: 8192_2-1-3-1-1-8_1440_0 + ja4t: 8192_2-1-3-1-1-8_1440_00 ja4l_c: 271_64 ja4l_s: 28494_61 ja4ssh: diff --git a/rust/ja4/src/snapshots/ja4__insta@v6.pcap.snap b/rust/ja4/src/snapshots/ja4__insta@v6.pcap.snap index cf446b9..97070ef 100644 --- a/rust/ja4/src/snapshots/ja4__insta@v6.pcap.snap +++ b/rust/ja4/src/snapshots/ja4__insta@v6.pcap.snap @@ -8,7 +8,7 @@ expression: output dst: 3ffe:501:410:0:2c0:dfff:fe47:33e src_port: 1022 dst_port: 22 - ja4t: 8192_2-1-3-1-1-8_1440_0 + ja4t: 8192_2-1-3-1-1-8_1440_00 ja4l_c: 271_64 ja4l_s: 28494_61 ja4ssh: diff --git a/rust/ja4/src/tcp.rs b/rust/ja4/src/tcp.rs index 3203aea..d3fcfbb 100644 --- a/rust/ja4/src/tcp.rs +++ b/rust/ja4/src/tcp.rs @@ -75,12 +75,12 @@ impl Stream { let mss = tcp .fields("tcp.options.mss_val") - .next() + .last() .map(|md| md.value().parse::()) .transpose()?; let window_scale = tcp .fields("tcp.options.wscale.shift") - .next() + .last() .map(|md| md.value().parse::()) .transpose()?; @@ -133,14 +133,18 @@ impl ClientStats { } let _ = write!(opts, "{}", v); } + if opts.is_empty() { + opts.push_str("00"); + } + + let mss = self.mss.unwrap_or(0); + let window_scale = self.window_scale.unwrap_or(0); - format!( - "{}_{}_{}_{}", - self.window_size, - opts, - self.mss.unwrap_or(0), - self.window_scale.unwrap_or(0), - ) + if window_scale == 0 { + format!("{}_{opts}_{mss:02}_{window_scale:02}", self.window_size) + } else { + format!("{}_{opts}_{mss:02}_{window_scale}", self.window_size) + } } } @@ -160,3 +164,42 @@ fn test_is_initial_syn() { // ACK without SYN assert!(!is_initial_syn(0x10)); } + +#[test] +fn test_ja4t_format_defaults() { + let client = ClientStats { + pkt_num: None, + window_size: 8192, + options: Vec::new(), + mss: None, + window_scale: None, + }; + + assert_eq!(client.to_ja4t(), "8192_00_00_00"); +} + +#[test] +fn test_ja4t_format_zero_window_scale() { + let client = ClientStats { + pkt_num: None, + window_size: 5744, + options: vec![2, 4, 8, 1, 3], + mss: Some(1436), + window_scale: Some(0), + }; + + assert_eq!(client.to_ja4t(), "5744_2-4-8-1-3_1436_00"); +} + +#[test] +fn test_ja4t_format_present_single_digit_mss() { + let client = ClientStats { + pkt_num: None, + window_size: 8192, + options: vec![2], + mss: Some(9), + window_scale: None, + }; + + assert_eq!(client.to_ja4t(), "8192_2_09_00"); +}