rama_net/fingerprint/
mod.rs

1//! fingerprint implementations for the network surface
2
3#[cfg(any(feature = "tls", feature = "http"))]
4mod ja4;
5
6#[cfg(feature = "http")]
7pub use ja4::{Ja4H, Ja4HComputeError};
8
9#[cfg(feature = "tls")]
10pub use ja4::{Ja4, Ja4ComputeError};
11
12#[cfg(feature = "tls")]
13mod ja3;
14
15#[cfg(feature = "tls")]
16pub use ja3::{Ja3, Ja3ComputeError};
17
18#[cfg(feature = "tls")]
19mod tls_utils {
20    use private::ClientHelloProviderPriv;
21
22    /// Sealed trait used by ja3/ja4 computation functions,
23    /// to allow you to immediately compute from either a
24    /// [`ClientHello`] or a [`ClientConfig`] data structure.
25    ///
26    /// [`ClientHello`]: crate::tls::client::ClientHello
27    /// [`ClientConfig`]: crate::tls::client::ClientConfig
28    pub trait ClientHelloProvider: ClientHelloProviderPriv {}
29    impl<P: ClientHelloProviderPriv> ClientHelloProvider for P {}
30
31    mod private {
32        use crate::tls::{
33            CipherSuite, ProtocolVersion,
34            client::{ClientConfig, ClientHello, ClientHelloExtension},
35        };
36
37        pub trait ClientHelloProviderPriv {
38            fn protocol_version(&self) -> ProtocolVersion;
39            fn cipher_suites(&self) -> impl Iterator<Item = CipherSuite>;
40            fn extensions(&self) -> impl Iterator<Item = &ClientHelloExtension>;
41        }
42
43        impl ClientHelloProviderPriv for &ClientHello {
44            fn protocol_version(&self) -> ProtocolVersion {
45                (*self).protocol_version()
46            }
47
48            fn cipher_suites(&self) -> impl Iterator<Item = CipherSuite> {
49                (*self).cipher_suites().iter().copied()
50            }
51
52            fn extensions(&self) -> impl Iterator<Item = &ClientHelloExtension> {
53                (*self).extensions().iter()
54            }
55        }
56
57        impl ClientHelloProviderPriv for &ClientConfig {
58            fn protocol_version(&self) -> ProtocolVersion {
59                ProtocolVersion::TLSv1_2
60            }
61
62            fn cipher_suites(&self) -> impl Iterator<Item = CipherSuite> {
63                self.cipher_suites.iter().flatten().copied()
64            }
65
66            fn extensions(&self) -> impl Iterator<Item = &ClientHelloExtension> {
67                self.extensions.iter().flatten()
68            }
69        }
70    }
71}
72
73#[cfg(feature = "tls")]
74pub use tls_utils::ClientHelloProvider;
75
76#[cfg(feature = "http")]
77mod http_utils {
78    use private::HttpRequestProviderPriv;
79    use rama_http_types::{Method, Version, proto::h1::Http1HeaderMap};
80
81    #[derive(Debug, Clone)]
82    /// Minimal input data structure which can be used
83    /// by ja4h computation functions instead of a reference
84    /// to a [`rama_http_types::Request`].
85    pub struct HttpRequestInput {
86        pub header_map: Http1HeaderMap,
87        pub http_method: Method,
88        pub version: Version,
89    }
90
91    /// Sealed trait used by the ja4h computation functions,
92    /// to allow you to immediately compute from either a
93    /// [`rama_http_types::Request`] or a [`HttpRequestInput`] data structure.
94    pub trait HttpRequestProvider: HttpRequestProviderPriv {}
95    impl<P: HttpRequestProviderPriv> HttpRequestProvider for P {}
96
97    mod private {
98        use super::*;
99        use rama_http_types::Request;
100
101        pub trait HttpRequestProviderPriv {
102            fn http_request_input(self) -> HttpRequestInput;
103        }
104
105        impl<B> HttpRequestProviderPriv for &Request<B> {
106            fn http_request_input(self) -> HttpRequestInput {
107                HttpRequestInput {
108                    header_map: Http1HeaderMap::copy_from_req(self),
109                    http_method: self.method().clone(),
110                    version: self.version(),
111                }
112            }
113        }
114
115        impl HttpRequestProviderPriv for HttpRequestInput {
116            fn http_request_input(self) -> HttpRequestInput {
117                self
118            }
119        }
120    }
121}
122
123#[cfg(feature = "http")]
124pub use http_utils::{HttpRequestInput, HttpRequestProvider};