From 08c6221ca47368b777dbe5643834a3b94b1ef4cb Mon Sep 17 00:00:00 2001 From: elpy Date: Wed, 8 Jul 2026 17:22:16 +1000 Subject: [PATCH] fix(ja4t): align Rust output with Wireshark/Zeek implementations --- .../ja4__insta@gre-erspan-vxlan.pcap.snap | 3 +- .../snapshots/ja4__insta@gre-sample.pcap.snap | 2 +- .../src/snapshots/ja4__insta@sshv1.pcap.snap | 2 +- .../ja4/src/snapshots/ja4__insta@v6.pcap.snap | 2 +- rust/ja4/src/tcp.rs | 62 ++++++++++++++----- 5 files changed, 50 insertions(+), 21 deletions(-) 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 7b74aad5..b12c094d 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 cb111bd6..f690e957 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 cf446b92..97070ef3 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 cf446b92..97070ef3 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 ae6ed3f8..ab0b598e 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()?; @@ -125,20 +125,24 @@ impl ClientStats { /// Example: /// 64240_2-1-3-1-1-4_1460_8 fn to_ja4t(&self) -> String { - let opts = self - .options - .iter() - .map(|v| v.to_string()) - .collect::>() - .join("-"); - - format!( - "{}_{}_{}_{}", - self.window_size, - opts, - self.mss.unwrap_or(0), - self.window_scale.unwrap_or(0), - ) + let opts = if self.options.is_empty() { + "00".to_owned() + } else { + self.options + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("-") + }; + + let mss = self.mss.unwrap_or(0); + let window_scale = 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) + } } } @@ -158,3 +162,29 @@ 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"); +}