Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pingora-cache/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,6 @@ default = []
openssl = ["pingora-core/openssl"]
boringssl = ["pingora-core/boringssl"]
rustls = ["pingora-core/rustls"]
rustls-no-ring = ["pingora-core/rustls-no-ring"]
s2n = ["pingora-core/s2n"]
trace = ["dep:cf-rustracing", "dep:cf-rustracing-jaeger"]
7 changes: 5 additions & 2 deletions pingora-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pingora-pool = { version = "0.8.0", path = "../pingora-pool" }
pingora-error = { version = "0.8.0", path = "../pingora-error" }
pingora-timeout = { version = "0.8.0", path = "../pingora-timeout" }
pingora-http = { version = "0.8.0", path = "../pingora-http" }
pingora-rustls = { version = "0.8.0", path = "../pingora-rustls", optional = true }
pingora-rustls = { version = "0.8.0", path = "../pingora-rustls", optional = true, default-features = false }
pingora-s2n = { version = "0.8.0", path = "../pingora-s2n", optional = true }
bstr = { workspace = true }
tokio = { workspace = true, features = ["net", "rt-multi-thread", "signal"] }
Expand Down Expand Up @@ -103,7 +103,10 @@ jemallocator = "0.5"
default = []
openssl = ["pingora-openssl", "openssl_derived"]
boringssl = ["pingora-boringssl", "openssl_derived"]
rustls = ["pingora-rustls", "any_tls", "dep:x509-parser", "ouroboros"]
rustls = ["rustls-base", "ring"]
rustls-no-ring = ["rustls-base"]
rustls-base = ["pingora-rustls", "any_tls", "dep:x509-parser", "ouroboros"]
ring = ["pingora-rustls/ring"]
s2n = ["pingora-s2n", "any_tls", "dep:x509-parser", "ouroboros", "lru"]
patched_http1 = ["pingora-http/patched_http1"]
openssl_derived = ["any_tls"]
Expand Down
8 changes: 4 additions & 4 deletions pingora-core/src/connectors/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,12 +369,12 @@ mod tests {
// Creates a test connector for integration/unit tests.
// For rustls, only ConnectorOptions are used here; the actual dangerous verifier is patched in the TLS connector.
fn create_test_connector() -> Connector<MockConnector> {
#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
let custom_transport = {
let options = ConnectorOptions::new(1);
TransportConnector::new(Some(options))
};
#[cfg(not(feature = "rustls"))]
#[cfg(not(feature = "rustls-base"))]
let custom_transport = TransportConnector::new(None);
Connector {
h1: v1::Connector::new(None),
Expand Down Expand Up @@ -490,7 +490,7 @@ mod tests {
// Both client and server are using custom protocols, but different ones - we should create H1 sessions as fallback.
// For RusTLS if there is no agreed protocol, the handshake directly fails, so this won't work
// TODO: If no ALPN is matched, rustls should return None instead of failing the handshake.
#[cfg(not(feature = "rustls"))]
#[cfg(not(feature = "rustls-base"))]
#[tokio::test]
async fn test_incompatible_custom_client_custom_upstream() {
let port = get_available_port().await;
Expand Down Expand Up @@ -569,7 +569,7 @@ mod tests {
}

// Used for disabling certificate/hostname verification in rustls for tests and custom ALPN/self-signed scenarios.
#[cfg(all(test, feature = "rustls"))]
#[cfg(all(test, feature = "rustls-base"))]
pub mod rustls_no_verify {
use rustls::client::danger::{ServerCertVerified, ServerCertVerifier};
use rustls::pki_types::{CertificateDer, ServerName};
Expand Down
8 changes: 4 additions & 4 deletions pingora-core/src/connectors/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ mod s2n;
#[cfg(feature = "s2n")]
pub use s2n::*;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
mod rustls;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
pub use rustls::*;

/// OpenSSL considers underscores in hostnames non-compliant.
Expand All @@ -41,7 +41,7 @@ pub use rustls::*;
/// > characters only letters, digits, and hyphen. There are also some
/// > restrictions on the length. Labels must be 63 characters or less.
/// - https://datatracker.ietf.org/doc/html/rfc1034#section-3.5
#[cfg(any(feature = "openssl_derived", feature = "rustls"))]
#[cfg(any(feature = "openssl_derived", feature = "rustls-base"))]
pub fn replace_leftmost_underscore(sni: &str) -> Option<String> {
// wildcard is only leftmost label
if let Some((leftmost, rest)) = sni.split_once('.') {
Expand All @@ -56,7 +56,7 @@ pub fn replace_leftmost_underscore(sni: &str) -> Option<String> {
None
}

#[cfg(any(feature = "openssl_derived", feature = "rustls"))]
#[cfg(any(feature = "openssl_derived", feature = "rustls-base"))]
#[cfg(test)]
mod tests {
use super::*;
Expand Down
1 change: 1 addition & 0 deletions pingora-core/src/connectors/tls/rustls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl TlsConnector {
Self: Sized,
{
// rustls 0.23+ requires an explicit CryptoProvider.
#[cfg(feature = "ring")]
pingora_rustls::install_default_crypto_provider();

// NOTE: Rustls only supports TLS 1.2 & 1.3
Expand Down
2 changes: 1 addition & 1 deletion pingora-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub use pingora_boringssl as tls;
#[cfg(feature = "openssl")]
pub use pingora_openssl as tls;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
pub use pingora_rustls as tls;

#[cfg(feature = "s2n")]
Expand Down
4 changes: 2 additions & 2 deletions pingora-core/src/listeners/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ mod boringssl_openssl;
#[cfg(feature = "openssl_derived")]
pub use boringssl_openssl::*;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
mod rustls;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
pub use rustls::*;

#[cfg(feature = "s2n")]
Expand Down
1 change: 1 addition & 0 deletions pingora-core/src/listeners/tls/rustls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ impl TlsSettings {
/// Todo: Return a result instead of panicking XD
pub fn build(self) -> Acceptor {
// rustls 0.23+ requires an explicit CryptoProvider.
#[cfg(feature = "ring")]
pingora_rustls::install_default_crypto_provider();

let Ok(Some((certs, key))) = load_certs_and_key_files(&self.cert_path, &self.key_path)
Expand Down
6 changes: 3 additions & 3 deletions pingora-core/src/protocols/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ mod boringssl_openssl;
#[cfg(feature = "openssl_derived")]
pub use boringssl_openssl::*;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
mod rustls;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
pub use rustls::*;

#[cfg(feature = "s2n")]
Expand Down Expand Up @@ -174,7 +174,7 @@ impl ALPN {
}
}

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
pub(crate) fn to_wire_protocols(&self) -> Vec<Vec<u8>> {
match self {
ALPN::H1 => vec![b"http/1.1".to_vec()],
Expand Down
7 changes: 6 additions & 1 deletion pingora-core/src/protocols/tls/rustls/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ use crate::protocols::{
use crate::utils::tls::get_organization_serial_bytes;
use pingora_error::ErrorType::{AcceptError, ConnectError, InternalError, TLSHandshakeFailure};
use pingora_error::{OkOrErr, OrErr, Result};
#[cfg(feature = "ring")]
use pingora_rustls::hash_certificate;
use pingora_rustls::NoDebug;
use pingora_rustls::TlsStream as RusTlsStream;
use pingora_rustls::{hash_certificate, NoDebug};
use pingora_rustls::{Accept, Connect, ServerName, TlsConnector};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use x509_parser::nom::AsBytes;
Expand Down Expand Up @@ -376,10 +378,13 @@ impl SslDigest {
.and_then(|proto| proto.as_str())
.unwrap_or_default();

#[cfg(feature = "ring")]
let cert_digest = peer_certificates
.and_then(|certs| certs.first())
.map(|cert| hash_certificate(cert))
.unwrap_or_default();
#[cfg(not(feature = "ring"))]
let cert_digest = Vec::new();

let (organization, serial_number) = peer_certificates
.and_then(|certs| certs.first())
Expand Down
4 changes: 2 additions & 2 deletions pingora-core/src/utils/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ mod boringssl_openssl;
#[cfg(feature = "openssl_derived")]
pub use boringssl_openssl::*;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
mod rustls;

#[cfg(feature = "rustls")]
#[cfg(feature = "rustls-base")]
pub use rustls::*;

#[cfg(feature = "s2n")]
Expand Down
1 change: 1 addition & 0 deletions pingora-load-balancing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ default = []
openssl = ["pingora-core/openssl", "openssl_derived"]
boringssl = ["pingora-core/boringssl", "openssl_derived"]
rustls = ["pingora-core/rustls", "any_tls"]
rustls-no-ring = ["pingora-core/rustls-no-ring", "any_tls"]
s2n = ["pingora-core/s2n", "any_tls"]
openssl_derived = ["any_tls"]
any_tls = []
Expand Down
1 change: 1 addition & 0 deletions pingora-proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ boringssl = [
"openssl_derived",
]
rustls = ["pingora-core/rustls", "pingora-cache/rustls", "any_tls"]
rustls-no-ring = ["pingora-core/rustls-no-ring", "pingora-cache/rustls-no-ring", "any_tls"]
s2n = ["pingora-core/s2n", "pingora-cache/s2n", "any_tls"]
openssl_derived = ["any_tls"]
any_tls = []
Expand Down
10 changes: 8 additions & 2 deletions pingora-rustls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ RusTLS async APIs for Pingora.
name = "pingora_rustls"
path = "src/lib.rs"

[features]
default = ["ring"]
# Use ring as the rustls CryptoProvider. Disable this feature when supplying
# your own provider (e.g. aws-lc-rs/fips, CNG, corecrypto).
ring = ["dep:ring", "rustls/ring"]

[dependencies]
log = "0.4.21"
pingora-error = { version = "0.8.0", path = "../pingora-error"}
ring = "0.17.12"
rustls = { version = "0.23.12", features = ["ring"] }
ring = { version = "0.17.12", optional = true }
rustls = { version = "0.23.12", default-features = false, features = ["logging", "std", "tls12"] }
rustls-native-certs = "0.7.1"
rustls-pemfile = "2.1.2"
rustls-pki-types = "1.7.0"
Expand Down
6 changes: 6 additions & 0 deletions pingora-rustls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ pub use rustls::{
/// rustls 0.23+ requires an explicit provider. This function installs `ring`
/// as the process-level default. Safe to call multiple times — subsequent
/// calls are no-ops.
///
/// Only available when the `ring` feature is enabled. When using a different
/// CryptoProvider (e.g. `aws-lc-rs`, CNG, corecrypto), install it yourself
/// before creating any TLS configuration.
#[cfg(feature = "ring")]
pub fn install_default_crypto_provider() {
let _ = CryptoProvider::install_default(rustls::crypto::ring::default_provider());
}
Expand Down Expand Up @@ -182,6 +187,7 @@ pub fn load_pem_file_private_key(path: &String) -> Result<Vec<u8>> {
.unwrap_or_default())
}

#[cfg(feature = "ring")]
pub fn hash_certificate(cert: &CertificateDer) -> Vec<u8> {
let hash = ring::digest::digest(&ring::digest::SHA256, cert.as_ref());
hash.as_ref().to_vec()
Expand Down
8 changes: 8 additions & 0 deletions pingora/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ rustls = [
"pingora-load-balancing?/rustls",
"any_tls",
]
## Use rustls without ring — bring your own CryptoProvider
rustls-no-ring = [
"pingora-core/rustls-no-ring",
"pingora-proxy?/rustls-no-ring",
"pingora-cache?/rustls-no-ring",
"pingora-load-balancing?/rustls-no-ring",
"any_tls",
]

#! ### Pingora extensions

Expand Down
Loading