wip: support rustls-0.23 for http3-quinn
This commit is contained in:
parent
0c6f3edf18
commit
234abae5dd
10 changed files with 63 additions and 53 deletions
|
|
@ -24,6 +24,9 @@ pub struct BackendApp {
|
|||
/// tls settings: https redirection with 30x
|
||||
#[builder(default)]
|
||||
pub https_redirection: Option<bool>,
|
||||
/// tls settings: mutual TLS is enabled
|
||||
#[builder(default)]
|
||||
pub mutual_tls: Option<bool>,
|
||||
}
|
||||
impl<'a> BackendAppBuilder {
|
||||
pub fn server_name(&mut self, server_name: impl Into<Cow<'a, str>>) -> &mut Self {
|
||||
|
|
@ -56,7 +59,10 @@ impl TryFrom<&AppConfig> for BackendApp {
|
|||
backend_builder.build()?
|
||||
} else {
|
||||
let tls = app_config.tls.as_ref().unwrap();
|
||||
backend_builder.https_redirection(Some(tls.https_redirection)).build()?
|
||||
backend_builder
|
||||
.https_redirection(Some(tls.https_redirection))
|
||||
.mutual_tls(Some(tls.mutual_tls))
|
||||
.build()?
|
||||
};
|
||||
Ok(backend)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,14 @@ pub enum RpxyError {
|
|||
NoServerNameInClientHello,
|
||||
#[error("No TLS serving app: {0}")]
|
||||
NoTlsServingApp(String),
|
||||
#[error("Failed to update server crypto: {0}")]
|
||||
FailedToUpdateServerCrypto(String),
|
||||
#[error("No server crypto: {0}")]
|
||||
NoServerCrypto(String),
|
||||
#[error("No default crypto provider")]
|
||||
NoDefaultCryptoProvider,
|
||||
#[error("Failed to build server config: {0}")]
|
||||
FailedToBuildServerConfig(String),
|
||||
// #[error("Failed to update server crypto: {0}")]
|
||||
// FailedToUpdateServerCrypto(String),
|
||||
// #[error("No server crypto: {0}")]
|
||||
// NoServerCrypto(String),
|
||||
|
||||
// hyper errors
|
||||
#[error("hyper body manipulation error: {0}")]
|
||||
|
|
|
|||
|
|
@ -157,5 +157,6 @@ pub struct UpstreamUri {
|
|||
/// Configuration parameters on TLS for a single backend application
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct TlsConfig {
|
||||
pub mutual_tls: bool,
|
||||
pub https_redirection: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,15 +29,15 @@ where
|
|||
{
|
||||
// Manipulate ALT_SVC allowing h3 in response message only when mutual TLS is not enabled
|
||||
// TODO: This is a workaround for avoiding a client authentication in HTTP/3
|
||||
if self.globals.proxy_config.http3 && backend_app.crypto_source.as_ref().is_some_and(|v| !v.is_mutual_tls()) {
|
||||
if self.globals.proxy_config.http3
|
||||
&& backend_app.https_redirection.is_some()
|
||||
&& backend_app.mutual_tls.as_ref().is_some_and(|v| !v)
|
||||
{
|
||||
if let Some(port) = self.globals.proxy_config.https_port {
|
||||
add_header_entry_overwrite_if_exist(
|
||||
headers,
|
||||
header::ALT_SVC.as_str(),
|
||||
format!(
|
||||
"h3=\":{}\"; ma={}, h3-29=\":{}\"; ma={}",
|
||||
port, self.globals.proxy_config.h3_alt_svc_max_age, port, self.globals.proxy_config.h3_alt_svc_max_age
|
||||
),
|
||||
format!("h3=\":{}\"; ma={}", port, self.globals.proxy_config.h3_alt_svc_max_age),
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use super::proxy_main::Proxy;
|
||||
use crate::{
|
||||
crypto::CryptoSource,
|
||||
error::*,
|
||||
hyper_ext::body::{IncomingLike, RequestBody},
|
||||
log::*,
|
||||
|
|
@ -17,10 +16,9 @@ use h3::{quic::BidiStream, quic::Connection as ConnectionQuic, server::RequestSt
|
|||
#[cfg(all(feature = "http3-s2n", not(feature = "http3-quinn")))]
|
||||
use s2n_quic_h3::h3::{self, quic::BidiStream, quic::Connection as ConnectionQuic, server::RequestStream};
|
||||
|
||||
impl<U, T> Proxy<U, T>
|
||||
impl<T> Proxy<T>
|
||||
where
|
||||
T: Connect + Clone + Sync + Send + 'static,
|
||||
U: CryptoSource + Clone + Sync + Send + 'static,
|
||||
{
|
||||
pub(super) async fn h3_serve_connection<C>(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
use super::proxy_main::Proxy;
|
||||
use super::socket::bind_udp_socket;
|
||||
use crate::{
|
||||
crypto::{CryptoSource, ServerCrypto},
|
||||
error::*,
|
||||
log::*,
|
||||
name_exp::ByteName,
|
||||
};
|
||||
use super::{proxy_main::Proxy, socket::bind_udp_socket};
|
||||
use crate::{error::*, log::*, name_exp::ByteName};
|
||||
use hyper_util::client::legacy::connect::Connect;
|
||||
use quinn::{crypto::rustls::HandshakeData, Endpoint, ServerConfig as QuicServerConfig, TransportConfig};
|
||||
use quinn::{
|
||||
crypto::rustls::{HandshakeData, QuicServerConfig},
|
||||
Endpoint, TransportConfig,
|
||||
};
|
||||
use rpxy_certs::ServerCrypto;
|
||||
use rustls::ServerConfig;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl<U, T> Proxy<U, T>
|
||||
impl<T> Proxy<T>
|
||||
where
|
||||
T: Send + Sync + Connect + Clone + 'static,
|
||||
U: CryptoSource + Clone + Sync + Send + 'static,
|
||||
{
|
||||
pub(super) async fn h3_listener_service(&self) -> RpxyResult<()> {
|
||||
let Some(mut server_crypto_rx) = self.globals.cert_reloader_rx.clone() else {
|
||||
|
|
@ -22,13 +19,14 @@ 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()
|
||||
// AWS LC provider by default
|
||||
let provider = rustls::crypto::CryptoProvider::get_default().ok_or(RpxyError::NoDefaultCryptoProvider)?;
|
||||
let rustls_server_config = ServerConfig::builder_with_provider(provider.clone())
|
||||
.with_protocol_versions(&[&rustls::version::TLS13])
|
||||
.map_err(|e| RpxyError::QuinnInvalidTlsProtocolVersion(e.to_string()))?
|
||||
.map_err(|e| RpxyError::FailedToBuildServerConfig(format!("TLS 1.3 server config failed: {e}")))?
|
||||
.with_no_client_auth()
|
||||
.with_cert_resolver(Arc::new(rustls::server::ResolvesServerCertUsingSni::new()));
|
||||
let quinn_server_config_crypto = QuicServerConfig::try_from(Arc::new(rustls_server_config)).unwrap();
|
||||
|
||||
let mut transport_config_quic = TransportConfig::default();
|
||||
transport_config_quic
|
||||
|
|
@ -42,20 +40,15 @@ where
|
|||
.map(|v| quinn::IdleTimeout::try_from(v).unwrap()),
|
||||
);
|
||||
|
||||
let mut server_config_h3 = QuicServerConfig::with_crypto(Arc::new(rustls_server_config));
|
||||
let mut server_config_h3 = quinn::ServerConfig::with_crypto(Arc::new(quinn_server_config_crypto));
|
||||
server_config_h3.transport = Arc::new(transport_config_quic);
|
||||
server_config_h3.concurrent_connections(self.globals.proxy_config.h3_max_concurrent_connections);
|
||||
server_config_h3.max_incoming(self.globals.proxy_config.h3_max_concurrent_connections as usize);
|
||||
|
||||
// To reuse address
|
||||
let udp_socket = bind_udp_socket(&self.listening_on)?;
|
||||
let runtime = quinn::default_runtime()
|
||||
.ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "No async runtime found"))?;
|
||||
let endpoint = Endpoint::new(
|
||||
quinn::EndpointConfig::default(),
|
||||
Some(server_config_h3),
|
||||
udp_socket,
|
||||
runtime,
|
||||
)?;
|
||||
let runtime =
|
||||
quinn::default_runtime().ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "No async runtime found"))?;
|
||||
let endpoint = Endpoint::new(quinn::EndpointConfig::default(), Some(server_config_h3), udp_socket, runtime)?;
|
||||
|
||||
let mut server_crypto: Option<Arc<ServerCrypto>> = None;
|
||||
loop {
|
||||
|
|
@ -64,8 +57,10 @@ where
|
|||
if server_crypto.is_none() || new_conn.is_none() {
|
||||
continue;
|
||||
}
|
||||
let mut conn: quinn::Connecting = new_conn.unwrap();
|
||||
let Ok(hsd) = conn.handshake_data().await else {
|
||||
let Ok(mut incoming) = new_conn.unwrap().accept() else {
|
||||
continue
|
||||
};
|
||||
let Ok(hsd) = incoming.handshake_data().await else {
|
||||
continue
|
||||
};
|
||||
|
||||
|
|
@ -84,8 +79,8 @@ where
|
|||
// TODO: 通常のTLSと同じenumか何かにまとめたい
|
||||
let self_clone = self.clone();
|
||||
self.globals.runtime_handle.spawn(async move {
|
||||
let client_addr = conn.remote_address();
|
||||
let quic_connection = match conn.await {
|
||||
let client_addr = incoming.remote_address();
|
||||
let quic_connection = match incoming.await {
|
||||
Ok(new_conn) => {
|
||||
info!("New connection established");
|
||||
h3_quinn::Connection::new(new_conn)
|
||||
|
|
@ -114,8 +109,12 @@ where
|
|||
error!("Failed to update server crypto for h3");
|
||||
break;
|
||||
};
|
||||
endpoint.set_server_config(Some(QuicServerConfig::with_crypto(inner.clone().inner_global_no_client_auth.clone())));
|
||||
|
||||
let rustls_server_config = inner.aggregated_config_no_client_auth.clone();
|
||||
let Ok(quinn_server_config_crypto) = QuicServerConfig::try_from(rustls_server_config) else {
|
||||
error!("Failed to update server crypto for h3");
|
||||
break;
|
||||
};
|
||||
endpoint.set_server_config(Some(quinn::ServerConfig::with_crypto(Arc::new(quinn_server_config_crypto))));
|
||||
}
|
||||
else => break
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue