diff --git a/rpxy-lib/Cargo.toml b/rpxy-lib/Cargo.toml index 699680a9..c472f324 100644 --- a/rpxy-lib/Cargo.toml +++ b/rpxy-lib/Cargo.toml @@ -71,8 +71,9 @@ hyper-rustls = { version = "0.27.1", default-features = false, features = [ # tls and cert management for server hot_reload = "0.1.5" -rustls = { version = "0.21.12", default-features = false } -tokio-rustls = { version = "0.24.1", features = ["early-data"] } +rustls = { version = "0.24.8", default-features = false, features = ["ring"] } +rustls-pki-types = { version = "1.0.1" } +tokio-rustls = { version = "0.26.0", features = ["early-data"] } webpki = "0.22.4" x509-parser = "0.16.0" diff --git a/rpxy-lib/src/crypto/certs.rs b/rpxy-lib/src/crypto/certs.rs index c9cfafd5..e8313493 100644 --- a/rpxy-lib/src/crypto/certs.rs +++ b/rpxy-lib/src/crypto/certs.rs @@ -1,10 +1,8 @@ use async_trait::async_trait; use rustc_hash::FxHashSet as HashSet; -use rustls::{ - sign::{any_supported_type, CertifiedKey}, - Certificate, OwnedTrustAnchor, PrivateKey, -}; -use std::io; +use rustls::{crypto::ring::sign::any_supported_type, sign::CertifiedKey}; +use rustls_pki_types::{CertificateDer as Certificate, Der, PrivateKeyDer as PrivateKey, TrustAnchor}; +use std::{io, sync::Arc}; use x509_parser::prelude::*; #[async_trait] @@ -22,9 +20,9 @@ pub trait CryptoSource { /// Certificates and private keys in rustls loaded from files #[derive(Debug, PartialEq, Eq, Clone)] pub struct CertsAndKeys { - pub certs: Vec, - pub cert_keys: Vec, - pub client_ca_certs: Option>, + pub certs: Vec>, + pub cert_keys: Arc>>, + pub client_ca_certs: Option>>, } impl CertsAndKeys { @@ -49,19 +47,19 @@ impl CertsAndKeys { Ok(CertifiedKey::new(self.certs.clone(), signing_key)) } - pub fn parse_client_ca_certs(&self) -> Result<(Vec, HashSet>), anyhow::Error> { + pub fn parse_client_ca_certs(&self) -> Result<(Vec, HashSet>), anyhow::Error> { let certs = self.client_ca_certs.as_ref().ok_or(anyhow::anyhow!("No client cert"))?; let owned_trust_anchors: Vec<_> = certs .iter() .map(|v| { // let trust_anchor = tokio_rustls::webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap(); - let trust_anchor = webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap(); - rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( - trust_anchor.subject, - trust_anchor.spki, - trust_anchor.name_constraints, - ) + let trust_anchor = webpki::TrustAnchor::try_from_cert_der(v.as_ref()).unwrap(); + TrustAnchor { + subject: Der::from_slice(trust_anchor.subject), + subject_public_key_info: Der::from_slice(trust_anchor.spki), + name_constraints: trust_anchor.name_constraints.map(|v| Der::from_slice(v)), + } }) .collect(); @@ -70,7 +68,7 @@ impl CertsAndKeys { .iter() .filter_map(|v| { // retrieve ca key id (subject key id) - let cert = parse_x509_certificate(&v.0).unwrap().1; + let cert = parse_x509_certificate(v.as_ref()).unwrap().1; let subject_key_ids = cert .iter_extensions() .filter_map(|ext| match ext.parsed_extension() { diff --git a/rpxy-lib/src/crypto/service.rs b/rpxy-lib/src/crypto/service.rs index cd198cb7..30cc1126 100644 --- a/rpxy-lib/src/crypto/service.rs +++ b/rpxy-lib/src/crypto/service.rs @@ -107,7 +107,8 @@ impl ServerCryptoBase { // add client certificate if specified match certs_and_keys.parse_client_ca_certs() { Ok((owned_trust_anchors, _subject_key_ids)) => { - client_ca_roots_local.add_trust_anchors(owned_trust_anchors.into_iter()); + client_ca_roots_local.extend(owned_trust_anchors); + // client_ca_roots_local.add_trust_anchors(owned_trust_anchors.into_iter()); } Err(e) => { warn!("Failed to add client CA certificate for {}: {}", server_name.as_str(), e); @@ -120,14 +121,12 @@ impl ServerCryptoBase { #[cfg(not(any(feature = "http3-quinn", feature = "http3-s2n")))] { ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_cert_resolver(Arc::new(resolver_local)) } #[cfg(any(feature = "http3-quinn", feature = "http3-s2n"))] { let mut sc = ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_cert_resolver(Arc::new(resolver_local)); sc.alpn_protocols = vec![b"h3".to_vec(), b"hq-29".to_vec()]; // TODO: remove hq-29 later? @@ -136,10 +135,20 @@ impl ServerCryptoBase { } else { // with client auth, enable only http1.1 and 2 // let client_certs_verifier = rustls::server::AllowAnyAnonymousOrAuthenticatedClient::new(client_ca_roots); - let client_certs_verifier = rustls::server::AllowAnyAuthenticatedClient::new(client_ca_roots_local); + let client_certs_verifier = + match rustls::server::WebPkiClientVerifier::builder(Arc::new(client_ca_roots_local)).build() { + Ok(v) => v, + Err(e) => { + warn!( + "Failed to build client CA certificate verifier for {}: {}", + server_name.as_str(), + e + ); + continue; + } + }; ServerConfig::builder() - .with_safe_defaults() - .with_client_cert_verifier(Arc::new(client_certs_verifier)) + .with_client_cert_verifier(client_certs_verifier) .with_cert_resolver(Arc::new(resolver_local)) }; server_config_local.alpn_protocols.push(b"h2".to_vec()); @@ -173,7 +182,6 @@ impl ServerCryptoBase { ////////////// let mut server_crypto_global = ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_cert_resolver(Arc::new(resolver_global)); diff --git a/rpxy-lib/src/error.rs b/rpxy-lib/src/error.rs index 3b1afc98..39fa91be 100644 --- a/rpxy-lib/src/error.rs +++ b/rpxy-lib/src/error.rs @@ -39,9 +39,6 @@ pub enum RpxyError { #[error("Exceeds max request body size for HTTP/3")] H3TooLargeBody, - #[cfg(feature = "http3-quinn")] - #[error("Invalid rustls TLS version: {0}")] - QuinnInvalidTlsProtocolVersion(String), #[cfg(feature = "http3-quinn")] #[error("Quinn connection error: {0}")] QuinnConnectionFailed(#[from] quinn::ConnectionError), diff --git a/rpxy-lib/src/lib.rs b/rpxy-lib/src/lib.rs index 115b78a4..22005fc1 100644 --- a/rpxy-lib/src/lib.rs +++ b/rpxy-lib/src/lib.rs @@ -24,7 +24,7 @@ pub use crate::{ }; pub mod reexports { pub use hyper::Uri; - pub use rustls::{Certificate, PrivateKey}; + pub use rustls_pki_types::{CertificateDer as Certificate, PrivateKeyDer as PrivateKey}; } /// Entrypoint that creates and spawns tasks of reverse proxy services diff --git a/rpxy-lib/src/proxy/proxy_quic_quinn.rs b/rpxy-lib/src/proxy/proxy_quic_quinn.rs index 9c4bf4e7..77a37662 100644 --- a/rpxy-lib/src/proxy/proxy_quic_quinn.rs +++ b/rpxy-lib/src/proxy/proxy_quic_quinn.rs @@ -22,11 +22,7 @@ where }; info!("Start UDP proxy serving with HTTP/3 request for configured host names [quinn]"); // first set as null config server - let rustls_server_config = ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&[&rustls::version::TLS13]) - .map_err(|e| RpxyError::QuinnInvalidTlsProtocolVersion(e.to_string()))? + let rustls_server_config = ServerConfig::builder_with_protocol_versions(&[&rustls::version::TLS13]) .with_no_client_auth() .with_cert_resolver(Arc::new(rustls::server::ResolvesServerCertUsingSni::new()));