From 427d65627cb475f21a49e4a8e2455dbda0664202 Mon Sep 17 00:00:00 2001 From: Alexey <247128645+axkurcom@users.noreply.github.com> Date: Mon, 23 Feb 2026 05:16:00 +0300 Subject: [PATCH] Drafting new TLS Fetcher --- src/tls_front/fetcher.rs | 56 ++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/src/tls_front/fetcher.rs b/src/tls_front/fetcher.rs index cf21c49..340bbab 100644 --- a/src/tls_front/fetcher.rs +++ b/src/tls_front/fetcher.rs @@ -418,23 +418,14 @@ async fn fetch_via_raw_tls( }) } -/// Fetch real TLS metadata for the given SNI: negotiated cipher and cert lengths. -pub async fn fetch_real_tls( +async fn fetch_via_rustls( host: &str, port: u16, sni: &str, connect_timeout: Duration, upstream: Option>, ) -> Result { - // Preferred path: raw TLS probe for accurate record sizing - match fetch_via_raw_tls(host, port, sni, connect_timeout).await { - Ok(res) => return Ok(res), - Err(e) => { - warn!(sni = %sni, error = %e, "Raw TLS fetch failed, falling back to rustls"); - } - } - - // Fallback: rustls handshake to at least get certificate sizes + // rustls handshake path for certificate and basic negotiated metadata. let stream = if let Some(manager) = upstream { // Resolve host to SocketAddr if let Ok(mut addrs) = tokio::net::lookup_host((host, port)).await { @@ -524,6 +515,49 @@ pub async fn fetch_real_tls( }) } +/// Fetch real TLS metadata for the given SNI. +/// +/// Strategy: +/// 1) Probe raw TLS for realistic ServerHello and ApplicationData record sizes. +/// 2) Fetch certificate chain via rustls to build cert payload. +/// 3) Merge both when possible; otherwise auto-fallback to whichever succeeded. +pub async fn fetch_real_tls( + host: &str, + port: u16, + sni: &str, + connect_timeout: Duration, + upstream: Option>, +) -> Result { + let raw_result = match fetch_via_raw_tls(host, port, sni, connect_timeout).await { + Ok(res) => Some(res), + Err(e) => { + warn!(sni = %sni, error = %e, "Raw TLS fetch failed"); + None + } + }; + + match fetch_via_rustls(host, port, sni, connect_timeout, upstream).await { + Ok(rustls_result) => { + if let Some(mut raw) = raw_result { + raw.cert_info = rustls_result.cert_info; + raw.cert_payload = rustls_result.cert_payload; + debug!(sni = %sni, "Fetched TLS metadata via raw probe + rustls cert chain"); + Ok(raw) + } else { + Ok(rustls_result) + } + } + Err(e) => { + if let Some(raw) = raw_result { + warn!(sni = %sni, error = %e, "Rustls cert fetch failed, using raw TLS metadata only"); + Ok(raw) + } else { + Err(e) + } + } + } +} + #[cfg(test)] mod tests { use super::encode_tls13_certificate_message;