fix(rustproxy): use SNI-based certificate resolution for QUIC TLS connections

This commit is contained in:
2026-03-20 08:06:32 +00:00
parent 2fce910795
commit 4ae09ac6ae
3 changed files with 19 additions and 31 deletions

View File

@@ -1003,44 +1003,25 @@ impl RustProxy {
fn build_quic_tls_config(
tls_configs: &HashMap<String, TlsCertConfig>,
) -> Option<Arc<rustls::ServerConfig>> {
// Find the first available cert (prefer wildcard, then any)
let cert_config = tls_configs.get("*")
.or_else(|| tls_configs.values().next());
let cert_config = match cert_config {
Some(c) => c,
None => return None,
};
// Parse cert chain from PEM
let mut cert_reader = std::io::BufReader::new(cert_config.cert_pem.as_bytes());
let certs: Vec<rustls::pki_types::CertificateDer<'static>> =
rustls_pemfile::certs(&mut cert_reader)
.filter_map(|r| r.ok())
.collect();
if certs.is_empty() {
if tls_configs.is_empty() {
return None;
}
// Parse private key from PEM
let mut key_reader = std::io::BufReader::new(cert_config.key_pem.as_bytes());
let key = match rustls_pemfile::private_key(&mut key_reader) {
Ok(Some(key)) => key,
_ => return None,
};
let mut tls_config = match rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)
{
Ok(c) => c,
// Reuse CertResolver for SNI-based cert selection (same as TCP/TLS path).
// This ensures QUIC connections get the correct certificate for each domain
// instead of a single static cert.
let resolver = match rustproxy_passthrough::tls_handler::CertResolver::new(tls_configs) {
Ok(r) => r,
Err(e) => {
warn!("Failed to build QUIC TLS config: {}", e);
warn!("Failed to build QUIC cert resolver: {}", e);
return None;
}
};
let mut tls_config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_cert_resolver(Arc::new(resolver));
// QUIC requires h3 ALPN
tls_config.alpn_protocols = vec![b"h3".to_vec()];