huginn_net_tls/output/
mod.rs1use crate::fingerprint::ObservableTlsClient;
2use std::fmt;
3use std::fmt::Formatter;
4
5#[derive(Debug, Clone, PartialEq)]
6#[cfg_attr(feature = "json", derive(serde::Serialize))]
7pub struct IpPort {
8 pub ip: std::net::IpAddr,
9 pub port: u16,
10}
11
12impl IpPort {
13 pub fn new(ip: std::net::IpAddr, port: u16) -> Self {
14 Self { ip, port }
15 }
16}
17
18#[derive(Debug)]
23#[cfg_attr(feature = "json", derive(serde::Serialize))]
24pub struct TlsClientOutput {
25 pub source: IpPort,
27 pub destination: IpPort,
29 #[cfg_attr(feature = "json", serde(serialize_with = "serialize_tls_client"))]
31 pub sig: ObservableTlsClient,
32}
33
34#[cfg(feature = "json")]
35fn serialize_tls_client<S: serde::Serializer>(
36 val: &ObservableTlsClient,
37 s: S,
38) -> Result<S::Ok, S::Error> {
39 use serde::ser::SerializeMap;
40 let mut map = s.serialize_map(None)?;
41 map.serialize_entry("sni", &val.sni)?;
42 map.serialize_entry("version", &val.version.to_string())?;
43 map.serialize_entry("alpn", &val.alpn)?;
44 map.serialize_entry("ja4", val.ja4.full.value())?;
45 map.serialize_entry("ja4_r", val.ja4.raw.value())?;
46 map.serialize_entry("ja4_o", val.ja4_original.full.value())?;
47 map.serialize_entry("ja4_or", val.ja4_original.raw.value())?;
48 #[cfg(feature = "stable-v1")]
49 map.serialize_entry("ja4_s1", val.ja4_stable_v1.full.value())?;
50 #[cfg(feature = "stable-v1")]
51 map.serialize_entry("ja4_s1r", val.ja4_stable_v1.raw.value())?;
52 map.end()
53}
54
55impl fmt::Display for TlsClientOutput {
56 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57 write!(
58 f,
59 "[TLS Client] {}:{} → {}:{}\n\
60 SNI: {}\n\
61 Version: TLS {}\n\
62 JA4: {}\n\
63 JA4_r: {}\n\
64 JA4_o: {}\n\
65 JA4_or: {}\n",
66 self.source.ip,
67 self.source.port,
68 self.destination.ip,
69 self.destination.port,
70 self.sig.sni.as_deref().unwrap_or("none"),
71 self.sig.version,
72 self.sig.ja4.full.value(),
73 self.sig.ja4.raw.value(),
74 self.sig.ja4_original.full.value(),
75 self.sig.ja4_original.raw.value(),
76 )?;
77 #[cfg(feature = "stable-v1")]
78 write!(
79 f,
80 "JA4_s1: {}\n\
81 JA4_s1r: {}\n",
82 self.sig.ja4_stable_v1.full.value(),
83 self.sig.ja4_stable_v1.raw.value(),
84 )?;
85 Ok(())
86 }
87}