exp
Some checks are pending
Unit Test / test (push) Waiting to run
ShiftLeft Scan / Scan-Build (push) Waiting to run

This commit is contained in:
ZettaScript 2025-10-13 15:25:15 +02:00
commit d9efeb42d6
11 changed files with 778 additions and 54 deletions

734
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -14,12 +14,13 @@ publish.workspace = true
[features] [features]
default = [ default = [
"http3-quinn", "provider-ring",
# "http3-quinn",
"cache", "cache",
"rustls-backend", "rustls-backend",
"sticky-cookie", "sticky-cookie",
"acme", # "acme",
"post-quantum", # "post-quantum",
] ]
# default = [ # default = [
# "http3-s2n", # "http3-s2n",
@ -29,6 +30,12 @@ default = [
# "acme", # "acme",
# "post-quantum", # "post-quantum",
# ] # ]
provider-aws-lc-rs = ["rpxy-lib/rustls-backend-aws-lc-rs"]
provider-boring = ["rpxy-lib/rustls-backend-boring"]
provider-openssl = ["rpxy-lib/rustls-backend-openssl"]
provider-ring = ["rpxy-lib/rustls-backend-ring"]
provider-symcrypt = ["rpxy-lib/rustls-backend-symcrypt"]
provider-wolfcrypt = ["rpxy-lib/rustls-backend-wolfcrypt"]
http3-quinn = ["rpxy-lib/http3-quinn"] http3-quinn = ["rpxy-lib/http3-quinn"]
http3-s2n = ["rpxy-lib/http3-s2n"] http3-s2n = ["rpxy-lib/http3-s2n"]
native-tls-backend = ["rpxy-lib/native-tls-backend"] native-tls-backend = ["rpxy-lib/native-tls-backend"]

View file

@ -173,6 +173,7 @@ pub struct ReverseProxyOption {
pub upstream: Vec<UpstreamParams>, pub upstream: Vec<UpstreamParams>,
pub upstream_options: Option<Vec<String>>, pub upstream_options: Option<Vec<String>>,
pub load_balance: Option<String>, pub load_balance: Option<String>,
pub set_host: Option<String>,
} }
#[derive(Deserialize, Debug, Default, PartialEq, Eq, Clone)] #[derive(Deserialize, Debug, Default, PartialEq, Eq, Clone)]
@ -398,6 +399,7 @@ impl TryInto<Vec<ReverseProxyConfig>> for &Application {
upstream, upstream,
upstream_options: rpo.upstream_options.clone(), upstream_options: rpo.upstream_options.clone(),
load_balance: rpo.load_balance.clone(), load_balance: rpo.load_balance.clone(),
set_host: rpo.set_host.clone(),
}) })
} }

View file

@ -13,6 +13,8 @@ publish.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
#default = ["rustls-backend", "rustls-backend-aws-lc-rs"]
http3-quinn = ["socket2", "quinn", "h3", "h3-quinn", "rpxy-certs/http3"] http3-quinn = ["socket2", "quinn", "h3", "h3-quinn", "rpxy-certs/http3"]
http3-s2n = [ http3-s2n = [
"s2n-quic", "s2n-quic",
@ -26,6 +28,12 @@ cache = ["http-cache-semantics", "lru", "sha2", "base64"]
sticky-cookie = ["base64", "sha2", "chrono"] sticky-cookie = ["base64", "sha2", "chrono"]
native-tls-backend = ["hyper-tls"] native-tls-backend = ["hyper-tls"]
rustls-backend = ["hyper-rustls"] rustls-backend = ["hyper-rustls"]
rustls-backend-aws-lc-rs = ["hyper-rustls/aws-lc-rs"]
rustls-backend-boring = ["hyper-rustls/aws-lc-rs", "boring-rustls-provider"]
rustls-backend-openssl = ["hyper-rustls/aws-lc-rs", "rustls-openssl"]
rustls-backend-ring = ["hyper-rustls/ring"]
rustls-backend-symcrypt = ["hyper-rustls/aws-lc-rs", "rustls-symcrypt"]
rustls-backend-wolfcrypt = ["hyper-rustls/aws-lc-rs", "rustls-wolfcrypt-provider"]
webpki-roots = ["rustls-backend", "hyper-rustls/webpki-tokio"] webpki-roots = ["rustls-backend", "hyper-rustls/webpki-tokio"]
acme = ["dep:rpxy-acme"] acme = ["dep:rpxy-acme"]
post-quantum = [ post-quantum = [
@ -71,7 +79,6 @@ hyper-tls = { version = "0.6.0", features = [
"vendored", "vendored",
], optional = true } ], optional = true }
hyper-rustls = { version = "0.27.7", default-features = false, features = [ hyper-rustls = { version = "0.27.7", default-features = false, features = [
"aws-lc-rs",
"http1", "http1",
"http2", "http2",
"rustls-platform-verifier", "rustls-platform-verifier",
@ -81,7 +88,11 @@ hyper-rustls = { version = "0.27.7", default-features = false, features = [
rpxy-certs = { path = "../rpxy-certs/", default-features = false } rpxy-certs = { path = "../rpxy-certs/", default-features = false }
hot_reload = "0.2.0" hot_reload = "0.2.0"
rustls = { version = "0.23.32", default-features = false } 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-post-quantum = { version = "0.2.4", 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 }
tokio-rustls = { version = "0.26.4", features = ["early-data"] } tokio-rustls = { version = "0.26.4", features = ["early-data"] }
# acme # acme
@ -94,11 +105,11 @@ tracing = { version = "0.1.41" }
quinn = { version = "0.11.9", optional = true } quinn = { version = "0.11.9", optional = true }
h3 = { version = "0.0.8", features = ["tracing"], optional = true } h3 = { version = "0.0.8", features = ["tracing"], optional = true }
h3-quinn = { version = "0.0.10", optional = true } h3-quinn = { version = "0.0.10", optional = true }
s2n-quic = { version = "1.67.0", path = "../submodules/s2n-quic/quic/s2n-quic/", default-features = false, features = [ s2n-quic = { path = "../submodules/s2n-quic/quic/s2n-quic/", default-features = false, features = [
"provider-tls-rustls", "provider-tls-rustls",
], optional = true } ], optional = true }
s2n-quic-core = { version = "0.67.0", path = "../submodules/s2n-quic/quic/s2n-quic-core", default-features = false, optional = true } s2n-quic-core = { path = "../submodules/s2n-quic/quic/s2n-quic-core", default-features = false, optional = true }
s2n-quic-rustls = { version = "0.67.0", path = "../submodules/s2n-quic/quic/s2n-quic-rustls", optional = true } s2n-quic-rustls = { path = "../submodules/s2n-quic/quic/s2n-quic-rustls", optional = true }
s2n-quic-h3 = { path = "../submodules/s2n-quic/quic/s2n-quic-h3/", features = [ s2n-quic-h3 = { path = "../submodules/s2n-quic/quic/s2n-quic-h3/", features = [
"tracing", "tracing",
], optional = true } ], optional = true }

View file

@ -40,6 +40,7 @@ impl TryFrom<&AppConfig> for PathManager {
.replace_path(&rpc.replace_path) .replace_path(&rpc.replace_path)
.load_balance(&rpc.load_balance, &upstream_vec, &app_config.server_name, &rpc.path) .load_balance(&rpc.load_balance, &upstream_vec, &app_config.server_name, &rpc.path)
.options(&rpc.upstream_options) .options(&rpc.upstream_options)
.set_host(&rpc.set_host)
.build() .build()
.unwrap(); .unwrap();
inner.insert(elem.path.clone(), elem); inner.insert(elem.path.clone(), elem);
@ -137,6 +138,9 @@ pub struct UpstreamCandidates {
#[builder(setter(custom), default)] #[builder(setter(custom), default)]
/// Activated upstream options defined in [[UpstreamOption]] /// Activated upstream options defined in [[UpstreamOption]]
pub options: HashSet<UpstreamOption>, pub options: HashSet<UpstreamOption>,
#[builder(setter(custom), default)]
pub set_host: Option<String>,
} }
impl UpstreamCandidatesBuilder { impl UpstreamCandidatesBuilder {
@ -218,6 +222,10 @@ impl UpstreamCandidatesBuilder {
self.options = Some(opts); self.options = Some(opts);
self self
} }
pub fn set_host(&mut self, set_host: &Option<String>) -> &mut Self {
self.set_host = Some(set_host.clone());
self
}
} }
impl UpstreamCandidates { impl UpstreamCandidates {

View file

@ -103,6 +103,7 @@ where
<B1 as Body>::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>, <B1 as Body>::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
{ {
async fn request_directly(&self, req: Request<B1>) -> RpxyResult<Response<Incoming>> { async fn request_directly(&self, req: Request<B1>) -> RpxyResult<Response<Incoming>> {
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. // 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. // Needs to be reconsidered. Currently, this is a kind of work around.
// This possibly relates to https://github.com/hyperium/hyper/issues/2417. // This possibly relates to https://github.com/hyperium/hyper/issues/2417.
@ -228,6 +229,7 @@ where
let inner = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())).build::<_, B1>(connector); let inner = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())).build::<_, B1>(connector);
let inner_h2 = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())) let inner_h2 = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone()))
.http2_only(true) .http2_only(true)
.set_host(false)
.build::<_, B1>(connector_h2); .build::<_, B1>(connector_h2);
Ok(Self { Ok(Self {

View file

@ -153,6 +153,7 @@ pub struct ReverseProxyConfig {
pub upstream: Vec<UpstreamUri>, pub upstream: Vec<UpstreamUri>,
pub upstream_options: Option<Vec<String>>, pub upstream_options: Option<Vec<String>>,
pub load_balance: Option<String>, pub load_balance: Option<String>,
pub set_host: Option<String>,
} }
/// Configuration parameters for single upstream destination from a reverse proxy /// Configuration parameters for single upstream destination from a reverse proxy

View file

@ -100,13 +100,43 @@ pub async fn entrypoint(
info!("Cache is disabled") info!("Cache is disabled")
} }
#[cfg(not(feature = "post-quantum"))] // Ensure multiple provider cannot be enabled without compile error.
// Install aws_lc_rs as default crypto provider for rustls let _provider;
let _ = CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_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());
}
#[cfg(feature = "rustls-backend-boring")]
{
info!("Using RusTLS provider boring");
_provider = CryptoProvider::install_default(boring_rustls_provider::provider());
}
#[cfg(feature = "rustls-backend-openssl")]
{
info!("Using RusTLS provider openssl");
_provider = CryptoProvider::install_default(rustls_openssl::default_provider());
}
#[cfg(feature = "post-quantum")] #[cfg(feature = "post-quantum")]
let _ = CryptoProvider::install_default(rustls_post_quantum::provider()); {
#[cfg(feature = "post-quantum")] info!("Using RusTLS provider post_quantum");
info!("Post-quantum crypto provider is installed"); _provider = CryptoProvider::install_default(rustls_post_quantum::provider());
}
#[cfg(feature = "rustls-backend-ring")]
{
info!("Using RusTLS provider ring");
_provider = CryptoProvider::install_default(rustls::crypto::ring::default_provider());
}
#[cfg(feature = "rustls-backend-symcrypt")]
{
info!("Using RusTLS provider symcrypt");
_provider = CryptoProvider::install_default(rustls_symcrypt::default_symcrypt_provider());
}
#[cfg(feature = "rustls-backend-wolfcrypt")]
{
info!("Using RusTLS provider wolfcrypt");
_provider = CryptoProvider::install_default(rustls_wolfcrypt_provider::provider());
}
// 1. build backends, and make it contained in Arc // 1. build backends, and make it contained in Arc
let app_manager = Arc::new(backend::BackendAppManager::try_from(app_config_list)?); let app_manager = Arc::new(backend::BackendAppManager::try_from(app_config_list)?);

View file

@ -168,6 +168,12 @@ where
// can update request line i.e., http version, only if not upgrade (http 1.1) // can update request line i.e., http version, only if not upgrade (http 1.1)
update_request_line(req, upstream_chosen, upstream_candidates)?; 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();
}
}
Ok(context) Ok(context)
} }

View file

@ -371,7 +371,8 @@ pub(super) fn host_from_uri_or_host_header(uri: &Uri, host_header_value: Option<
// Prioritize uri host over host header // Prioritize uri host over host header
let uri_host = uri.host().map(|host| { let uri_host = uri.host().map(|host| {
if let Some(port) = uri.port_u16() { if let Some(port) = uri.port_u16() {
format!("{}:{}", host, port) //format!("{}:{}", host, port)
host.to_string()
} else { } else {
host.to_string() host.to_string()
} }

@ -1 +1 @@
Subproject commit 687df9619843a335b64e46f20091bda45b054d8e Subproject commit 19d80dc650f30d2488f97e5cc0f4935927908782