diff --git a/src/tls_front/fetcher.rs b/src/tls_front/fetcher.rs index 39a4609..44504d8 100644 --- a/src/tls_front/fetcher.rs +++ b/src/tls_front/fetcher.rs @@ -1,19 +1,22 @@ use std::sync::Arc; use std::time::Duration; +use anyhow::Result; use tokio::net::TcpStream; use tokio::time::timeout; use tokio_rustls::client::TlsStream; use tokio_rustls::TlsConnector; -use tracing::{debug, warn}; +use tracing::debug; -use rustls::client::{ClientConfig, ServerCertVerifier, ServerName}; +use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::client::ClientConfig; +use rustls::pki_types::{CertificateDer, ServerName, UnixTime}; use rustls::{DigitallySignedStruct, Error as RustlsError}; -use rustls::pki_types::{ServerName as PkiServerName, UnixTime, CertificateDer}; use crate::tls_front::types::{ParsedServerHello, TlsFetchResult}; /// No-op verifier: accept any certificate (we only need lengths and metadata). +#[derive(Debug)] struct NoVerify; impl ServerCertVerifier for NoVerify { @@ -21,11 +24,11 @@ impl ServerCertVerifier for NoVerify { &self, _end_entity: &CertificateDer<'_>, _intermediates: &[CertificateDer<'_>], - _server_name: &PkiServerName<'_>, + _server_name: &ServerName<'_>, _ocsp: &[u8], _now: UnixTime, - ) -> Result { - Ok(rustls::client::ServerCertVerified::assertion()) + ) -> Result { + Ok(ServerCertVerified::assertion()) } fn verify_tls12_signature( @@ -33,8 +36,8 @@ impl ServerCertVerifier for NoVerify { _message: &[u8], _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, - ) -> Result { - Ok(rustls::client::HandshakeSignatureValid::assertion()) + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) } fn verify_tls13_signature( @@ -42,57 +45,67 @@ impl ServerCertVerifier for NoVerify { _message: &[u8], _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, - ) -> Result { - Ok(rustls::client::HandshakeSignatureValid::assertion()) + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn supported_verify_schemes(&self) -> Vec { + use rustls::SignatureScheme::*; + vec![ + RSA_PKCS1_SHA256, + RSA_PSS_SHA256, + ECDSA_NISTP256_SHA256, + ECDSA_NISTP384_SHA384, + ] } } fn build_client_config() -> Arc { - let mut root = rustls::RootCertStore::empty(); - // Optionally load system roots; failure is non-fatal. - let _ = root.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + let root = rustls::RootCertStore::empty(); - Arc::new( - ClientConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&[&rustls::version::TLS13, &rustls::version::TLS12]) - .unwrap() - .with_custom_certificate_verifier(Arc::new(NoVerify)) - .with_root_certificates(root) - .with_no_client_auth(), - ) + let provider = rustls::crypto::ring::default_provider(); + let mut config = ClientConfig::builder_with_provider(Arc::new(provider)) + .with_protocol_versions(&[&rustls::version::TLS13, &rustls::version::TLS12]) + .expect("protocol versions") + .with_root_certificates(root) + .with_no_client_auth(); + + config + .dangerous() + .set_certificate_verifier(Arc::new(NoVerify)); + + Arc::new(config) } -/// Try to fetch real TLS metadata for the given SNI. +/// Fetch real TLS metadata for the given SNI: negotiated cipher and cert lengths. pub async fn fetch_real_tls( host: &str, port: u16, sni: &str, connect_timeout: Duration, -) -> anyhow::Result { - let addr = format!("{}:{}", host, port); +) -> Result { + let addr = format!("{host}:{port}"); let stream = timeout(connect_timeout, TcpStream::connect(addr)).await??; let config = build_client_config(); let connector = TlsConnector::from(config); - let server_name = ServerName::try_from(sni) - .or_else(|_| ServerName::try_from(host)) + let server_name = ServerName::try_from(sni.to_owned()) + .or_else(|_| ServerName::try_from(host.to_owned())) .map_err(|_| RustlsError::General("invalid SNI".into()))?; - let mut tls_stream: TlsStream = connector.connect(server_name, stream).await?; + let tls_stream: TlsStream = connector.connect(server_name, stream).await?; // Extract negotiated parameters and certificates - let (session, _io) = tls_stream.get_ref(); + let (_io, session) = tls_stream.get_ref(); let cipher_suite = session .negotiated_cipher_suite() - .map(|s| s.suite().get_u16().to_be_bytes()) + .map(|s| u16::from(s.suite()).to_be_bytes()) .unwrap_or([0x13, 0x01]); let certs: Vec> = session .peer_certificates() - .map(|slice| slice.iter().cloned().collect()) + .map(|slice| slice.to_vec()) .unwrap_or_default(); let total_cert_len: usize = certs.iter().map(|c| c.len()).sum::().max(1024); diff --git a/src/transport/socket.rs b/src/transport/socket.rs index 7113afc..f353c52 100644 --- a/src/transport/socket.rs +++ b/src/transport/socket.rs @@ -138,7 +138,7 @@ pub fn resolve_interface_ip(name: &str, want_ipv6: bool) -> Option { } } else if let Some(v6) = address.as_sockaddr_in6() { if want_ipv6 { - return Some(IpAddr::V6(v6.ip().to_std())); + return Some(IpAddr::V6(v6.ip().clone())); } } } diff --git a/src/transport/upstream.rs b/src/transport/upstream.rs index 28319d3..660043f 100644 --- a/src/transport/upstream.rs +++ b/src/transport/upstream.rs @@ -609,7 +609,7 @@ impl UpstreamManager { } let result = tokio::time::timeout( Duration::from_secs(DC_PING_TIMEOUT_SECS), - self.ping_single_dc(&upstream_config, addr) + self.ping_single_dc(&upstream_config, Some(bind_rr.clone()), addr) ).await; let ping_result = match result {