diff --git a/rpxy-certs/src/certs.rs b/rpxy-certs/src/certs.rs index 56d062a..4e27873 100644 --- a/rpxy-certs/src/certs.rs +++ b/rpxy-certs/src/certs.rs @@ -65,7 +65,7 @@ impl SingleServerCertsKeys { .cert_keys .clone() .iter() - .find_map(|k| any_supported_type(k).ok()) + .find_map(|k| dbg!(any_supported_type(k)).ok()) .ok_or_else(|| RpxyCertError::InvalidCertificateAndKey)?; let cert = self.certs.iter().map(|c| Certificate::from(c.to_vec())).collect::>(); diff --git a/rpxy-certs/src/lib.rs b/rpxy-certs/src/lib.rs index 9abdfc4..1c476df 100644 --- a/rpxy-certs/src/lib.rs +++ b/rpxy-certs/src/lib.rs @@ -42,11 +42,11 @@ where T: CryptoSource + Send + Sync + Clone + 'static, { info!("Building certificate reloader service"); - #[cfg(not(feature = "post-quantum"))] + /*#[cfg(not(feature = "post-quantum"))] // Install aws_lc_rs as default crypto provider for rustls let _ = CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_provider()); #[cfg(feature = "post-quantum")] - let _ = CryptoProvider::install_default(rustls_post_quantum::provider()); + let _ = CryptoProvider::install_default(rustls_post_quantum::provider());*/ let source = crypto_source_map .iter() diff --git a/rpxy-lib/Cargo.toml b/rpxy-lib/Cargo.toml index f30ed16..048f2f6 100644 --- a/rpxy-lib/Cargo.toml +++ b/rpxy-lib/Cargo.toml @@ -89,7 +89,7 @@ rpxy-certs = { path = "../rpxy-certs/", default-features = false } hot_reload = "0.2.0" rustls = { version = "0.23.32", default-features = false } boring-rustls-provider = { git = "https://github.com/janrueth/boring-rustls-provider.git", rev = "490340afa77e2c08fc45853124f99d49f4f9f8a0", optional = true } -rustls-openssl = { version = "0.3.0", default-features = false, optional = true } +rustls-openssl = { version = "0.3.0", default-features = false, features = ["tls12"], optional = true } rustls-post-quantum = { version = "0.2.4", optional = true } rustls-symcrypt = { version = "0.2.1", optional = true, features = ["chacha", "x25519"] } rustls-wolfcrypt-provider = { git = "https://github.com/wolfSSL/rustls-wolfcrypt-provider.git", rev = "dfcdbfdba3a988494503886151f732ee0bd56c7d", optional = true } diff --git a/rpxy-lib/src/forwarder/client.rs b/rpxy-lib/src/forwarder/client.rs index df4cab8..3e53297 100644 --- a/rpxy-lib/src/forwarder/client.rs +++ b/rpxy-lib/src/forwarder/client.rs @@ -103,7 +103,10 @@ where ::Error: Into>, { async fn request_directly(&self, req: Request) -> RpxyResult> { - debug!("About to send request with Host header: {}", req.headers().get(hyper::header::HOST).unwrap().to_str().unwrap()); + debug!( + "About to send request with Host header: {}", + req.headers().get(hyper::header::HOST).unwrap().to_str().unwrap() + ); // TODO: This 'match' condition is always evaluated at every 'request' invocation. So, it is inefficient. // Needs to be reconsidered. Currently, this is a kind of work around. // This possibly relates to https://github.com/hyperium/hyper/issues/2417. diff --git a/rpxy-lib/src/lib.rs b/rpxy-lib/src/lib.rs index c2628c9..2062424 100644 --- a/rpxy-lib/src/lib.rs +++ b/rpxy-lib/src/lib.rs @@ -100,22 +100,185 @@ pub async fn entrypoint( info!("Cache is disabled") } + let mut ciphers: Option> = None; + let mut kexes: Option> = None; + for (var, val) in std::env::vars() { + match var.as_str() { + "CIPHERS" => ciphers = Some(val.split(',').map(str::to_string).collect()), + "KEXES" => kexes = Some(val.split(',').map(str::to_string).collect()), + _ => {} + } + } // Ensure multiple provider cannot be enabled without compile error. let _provider; #[cfg(feature = "rustls-backend-aws-lc-rs")] { info!("Using RusTLS provider aws-lc-rs"); - _provider = CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_provider()); + let mut prov = rustls::crypto::aws_lc_rs::default_provider(); + if let Some(ciphers) = ciphers { + prov.cipher_suites.clear(); + for cipher in ciphers { + match cipher.as_str() { + "AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS13_AES_256_GCM_SHA384), + "AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS13_AES_128_GCM_SHA256), + "CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), + "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), + "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls::crypto::aws_lc_rs::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), + other => { + log::error!("Unknown cipher `{other}`") + } + } + } + } + if let Some(kexes) = kexes { + prov.kx_groups.clear(); + for kex in kexes { + match kex.as_str() { + "X25519" => prov.kx_groups.push(rustls::crypto::aws_lc_rs::kx_group::X25519), + "SECP256R1" => prov.kx_groups.push(rustls::crypto::aws_lc_rs::kx_group::SECP256R1), + "SECP384R1" => prov.kx_groups.push(rustls::crypto::aws_lc_rs::kx_group::SECP384R1), + other => { + log::error!("Unknown kex `{other}`") + } + } + } + } + _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "rustls-backend-boring")] { info!("Using RusTLS provider boring"); - _provider = CryptoProvider::install_default(boring_rustls_provider::provider()); + let mut prov = boring_rustls_provider::provider(); + if let Some(ciphers) = ciphers { + prov.cipher_suites.clear(); + for cipher in ciphers { + match cipher.as_str() { + "AES_256_GCM_SHA384" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls13( + &boring_rustls_provider::tls13::AES_256_GCM_SHA384, + )), + "AES_128_GCM_SHA256" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls13( + &boring_rustls_provider::tls13::AES_128_GCM_SHA256, + )), + "CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls13( + &boring_rustls_provider::tls13::CHACHA20_POLY1305_SHA256, + )), + "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls12( + &boring_rustls_provider::tls12::ECDHE_ECDSA_AES256_GCM_SHA384, + )), + "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls12( + &boring_rustls_provider::tls12::ECDHE_ECDSA_AES128_GCM_SHA256, + )), + "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls12( + &boring_rustls_provider::tls12::ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + )), + "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls12( + &boring_rustls_provider::tls12::ECDHE_RSA_AES256_GCM_SHA384, + )), + "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls12( + &boring_rustls_provider::tls12::ECDHE_RSA_AES128_GCM_SHA256, + )), + "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(rustls::SupportedCipherSuite::Tls12( + &boring_rustls_provider::tls12::ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + )), + other => { + log::error!("Unknown cipher `{other}`") + } + } + } + } + if let Some(kexes) = kexes { + prov.kx_groups.clear(); + for kex in kexes { + match kex.as_str() { + "X25519" => prov.kx_groups.push(boring_rustls_provider::ALL_KX_GROUPS[0]), + "SECP256R1" => prov.kx_groups.push(boring_rustls_provider::ALL_KX_GROUPS[2]), + "SECP384R1" => prov.kx_groups.push(boring_rustls_provider::ALL_KX_GROUPS[3]), + other => { + log::error!("Unknown kex `{other}`") + } + } + } + } + _provider = CryptoProvider::install_default(prov); } + #[cfg(feature = "rustls-backend-openssl")] { info!("Using RusTLS provider openssl"); - _provider = CryptoProvider::install_default(rustls_openssl::default_provider()); + let mut prov = rustls_openssl::default_provider(); + if let Some(ciphers) = ciphers { + prov.cipher_suites.clear(); + for cipher in ciphers { + match cipher.as_str() { + "AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS13_AES_256_GCM_SHA384), + "AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS13_AES_128_GCM_SHA256), + "CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), + "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), + "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls_openssl::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), + other => { + log::error!("Unknown cipher `{other}`") + } + } + } + } + if let Some(kexes) = kexes { + prov.kx_groups.clear(); + for kex in kexes { + match kex.as_str() { + "X25519" => prov.kx_groups.push(rustls_openssl::kx_group::X25519), + "SECP256R1" => prov.kx_groups.push(rustls_openssl::kx_group::SECP256R1), + "SECP384R1" => prov.kx_groups.push(rustls_openssl::kx_group::SECP384R1), + other => { + log::error!("Unknown kex `{other}`") + } + } + } + } + _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "post-quantum")] { @@ -125,12 +288,108 @@ pub async fn entrypoint( #[cfg(feature = "rustls-backend-ring")] { info!("Using RusTLS provider ring"); - _provider = CryptoProvider::install_default(rustls::crypto::ring::default_provider()); + let mut prov = rustls::crypto::ring::default_provider(); + if let Some(ciphers) = ciphers { + prov.cipher_suites.clear(); + for cipher in ciphers { + match cipher.as_str() { + "AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS13_AES_256_GCM_SHA384), + "AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS13_AES_128_GCM_SHA256), + "CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), + "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), + "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls::crypto::ring::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), + other => { + log::error!("Unknown cipher `{other}`") + } + } + } + } + if let Some(kexes) = kexes { + prov.kx_groups.clear(); + for kex in kexes { + match kex.as_str() { + "X25519" => prov.kx_groups.push(rustls::crypto::ring::kx_group::X25519), + "SECP256R1" => prov.kx_groups.push(rustls::crypto::ring::kx_group::SECP256R1), + "SECP384R1" => prov.kx_groups.push(rustls::crypto::ring::kx_group::SECP384R1), + other => { + log::error!("Unknown kex `{other}`") + } + } + } + } + _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "rustls-backend-symcrypt")] { info!("Using RusTLS provider symcrypt"); - _provider = CryptoProvider::install_default(rustls_symcrypt::default_symcrypt_provider()); + let mut prov = rustls_symcrypt::default_symcrypt_provider(); + if let Some(ciphers) = ciphers { + prov.cipher_suites.clear(); + for cipher in ciphers { + match cipher.as_str() { + "AES_256_GCM_SHA384" => prov.cipher_suites.push(rustls_symcrypt::TLS13_AES_256_GCM_SHA384), + "AES_128_GCM_SHA256" => prov.cipher_suites.push(rustls_symcrypt::TLS13_AES_128_GCM_SHA256), + "CHACHA20_POLY1305_SHA256" => prov.cipher_suites.push(rustls_symcrypt::TLS13_CHACHA20_POLY1305_SHA256), + "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls_symcrypt::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls_symcrypt::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls_symcrypt::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), + "ECDHE_RSA_WITH_AES_256_GCM_SHA384" => prov + .cipher_suites + .push(rustls_symcrypt::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + "ECDHE_RSA_WITH_AES_128_GCM_SHA256" => prov + .cipher_suites + .push(rustls_symcrypt::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => prov + .cipher_suites + .push(rustls_symcrypt::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), + other => { + log::error!("Unknown cipher `{other}`") + } + } + } + } + if let Some(kexes) = kexes { + prov.kx_groups.clear(); + for kex in kexes { + match kex.as_str() { + "X25519" => prov.kx_groups.push(rustls_symcrypt::X25519), + "SECP256R1" => prov.kx_groups.push(rustls_symcrypt::SECP256R1), + "SECP384R1" => prov.kx_groups.push(rustls_symcrypt::SECP384R1), + other => { + log::error!("Unknown kex `{other}`") + } + } + } + } + _provider = CryptoProvider::install_default(prov); } #[cfg(feature = "rustls-backend-wolfcrypt")] { diff --git a/rpxy-lib/src/message_handler/handler_manipulate_messages.rs b/rpxy-lib/src/message_handler/handler_manipulate_messages.rs index 56aa3d3..bc10fbf 100644 --- a/rpxy-lib/src/message_handler/handler_manipulate_messages.rs +++ b/rpxy-lib/src/message_handler/handler_manipulate_messages.rs @@ -168,7 +168,7 @@ where // can update request line i.e., http version, only if not upgrade (http 1.1) update_request_line(req, upstream_chosen, upstream_candidates)?; } - + if let Some(set_host) = &upstream_candidates.set_host { if let Some(host) = req.headers_mut().get_mut(&header::HOST) { *host = HeaderValue::from_str(set_host).unwrap();