diff --git a/src/backend/mod.rs b/src/backend/mod.rs index c8298c3..524f30b 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -13,14 +13,20 @@ pub use self::{ upstream::{ReverseProxy, Upstream, UpstreamGroup, UpstreamGroupBuilder}, upstream_opts::UpstreamOption, }; -use crate::utils::{BytesName, PathNameBytesExp, ServerNameBytesExp}; +use crate::{ + certs::CryptoSource, + utils::{BytesName, PathNameBytesExp, ServerNameBytesExp}, +}; use derive_builder::Builder; use rustc_hash::FxHashMap as HashMap; -use std::{borrow::Cow, path::PathBuf}; +use std::borrow::Cow; /// Struct serving information to route incoming connections, like server name to be handled and tls certs/keys settings. #[derive(Builder)] -pub struct Backend { +pub struct Backend +where + T: CryptoSource, +{ #[builder(setter(into))] /// backend application name, e.g., app1 pub app_name: String, @@ -30,42 +36,41 @@ pub struct Backend { /// struct of reverse proxy serving incoming request pub reverse_proxy: ReverseProxy, - /// tls settings - #[builder(setter(custom), default)] - pub tls_cert_path: Option, - #[builder(setter(custom), default)] - pub tls_cert_key_path: Option, + /// tls settings: https redirection with 30x #[builder(default)] pub https_redirection: Option, - #[builder(setter(custom), default)] - pub client_ca_cert_path: Option, + + /// TLS settings: source meta for server cert, key, client ca cert + #[builder(default)] + pub crypto_source: Option, } -impl<'a> BackendBuilder { +impl<'a, T> BackendBuilder +where + T: CryptoSource, +{ pub fn server_name(&mut self, server_name: impl Into>) -> &mut Self { self.server_name = Some(server_name.into().to_ascii_lowercase()); self } - pub fn tls_cert_path(&mut self, v: &Option) -> &mut Self { - self.tls_cert_path = Some(opt_string_to_opt_pathbuf(v)); - self - } - pub fn tls_cert_key_path(&mut self, v: &Option) -> &mut Self { - self.tls_cert_key_path = Some(opt_string_to_opt_pathbuf(v)); - self - } - pub fn client_ca_cert_path(&mut self, v: &Option) -> &mut Self { - self.client_ca_cert_path = Some(opt_string_to_opt_pathbuf(v)); - self - } } -fn opt_string_to_opt_pathbuf(input: &Option) -> Option { - input.to_owned().as_ref().map(PathBuf::from) -} - -#[derive(Default)] /// HashMap and some meta information for multiple Backend structs. -pub struct Backends { - pub apps: HashMap, // hyper::uriで抜いたhostで引っ掛ける +pub struct Backends +where + T: CryptoSource, +{ + pub apps: HashMap>, // hyper::uriで抜いたhostで引っ掛ける pub default_server_name_bytes: Option, // for plaintext http } + +impl Backends +where + T: CryptoSource, +{ + pub fn new() -> Self { + Backends { + apps: HashMap::>::default(), + default_server_name_bytes: None, + } + } +} diff --git a/src/cert_file_reader.rs b/src/cert_file_reader.rs new file mode 100644 index 0000000..e25dcf7 --- /dev/null +++ b/src/cert_file_reader.rs @@ -0,0 +1,185 @@ +use crate::{ + certs::{CertsAndKeys, CryptoSource}, + log::*, +}; +use async_trait::async_trait; +use derive_builder::Builder; +use rustls::{Certificate, PrivateKey}; +use std::{ + fs::File, + io::{self, BufReader, Cursor, Read}, + path::PathBuf, +}; + +#[derive(Builder, Debug, Clone)] +/// Crypto-related file reader implementing certs::CryptoRead trait +pub struct CryptoFileSource { + #[builder(setter(custom))] + /// Always exist + pub tls_cert_path: PathBuf, + + #[builder(setter(custom))] + /// Always exist + pub tls_cert_key_path: PathBuf, + + #[builder(setter(custom), default)] + /// This may not exist + pub client_ca_cert_path: Option, +} + +impl CryptoFileSourceBuilder { + pub fn tls_cert_path(&mut self, v: &str) -> &mut Self { + self.tls_cert_path = Some(PathBuf::from(v)); + self + } + pub fn tls_cert_key_path(&mut self, v: &str) -> &mut Self { + self.tls_cert_key_path = Some(PathBuf::from(v)); + self + } + pub fn client_ca_cert_path(&mut self, v: &Option) -> &mut Self { + self.client_ca_cert_path = Some(v.to_owned().as_ref().map(PathBuf::from)); + self + } +} + +#[async_trait] +impl CryptoSource for CryptoFileSource { + type Error = io::Error; + /// read crypto materials from source + async fn read(&self) -> Result { + read_certs_and_keys( + &self.tls_cert_path, + &self.tls_cert_key_path, + self.client_ca_cert_path.as_ref(), + ) + } + /// Returns true when mutual tls is enabled + fn is_mutual_tls(&self) -> bool { + self.client_ca_cert_path.is_some() + } +} + +/// Read certificates and private keys from file +fn read_certs_and_keys( + cert_path: &PathBuf, + cert_key_path: &PathBuf, + client_ca_cert_path: Option<&PathBuf>, +) -> Result { + debug!("Read TLS server certificates and private key"); + + let certs: Vec<_> = { + let certs_path_str = cert_path.display().to_string(); + let mut reader = BufReader::new(File::open(cert_path).map_err(|e| { + io::Error::new( + e.kind(), + format!("Unable to load the certificates [{certs_path_str}]: {e}"), + ) + })?); + rustls_pemfile::certs(&mut reader) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Unable to parse the certificates"))? + } + .drain(..) + .map(Certificate) + .collect(); + + let cert_keys: Vec<_> = { + let cert_key_path_str = cert_key_path.display().to_string(); + let encoded_keys = { + let mut encoded_keys = vec![]; + File::open(cert_key_path) + .map_err(|e| { + io::Error::new( + e.kind(), + format!("Unable to load the certificate keys [{cert_key_path_str}]: {e}"), + ) + })? + .read_to_end(&mut encoded_keys)?; + encoded_keys + }; + let mut reader = Cursor::new(encoded_keys); + let pkcs8_keys = rustls_pemfile::pkcs8_private_keys(&mut reader).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidInput, + "Unable to parse the certificates private keys (PKCS8)", + ) + })?; + reader.set_position(0); + let mut rsa_keys = rustls_pemfile::rsa_private_keys(&mut reader)?; + let mut keys = pkcs8_keys; + keys.append(&mut rsa_keys); + if keys.is_empty() { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "No private keys found - Make sure that they are in PKCS#8/PEM format", + )); + } + keys.drain(..).map(PrivateKey).collect() + }; + + let client_ca_certs = if let Some(path) = client_ca_cert_path { + debug!("Read CA certificates for client authentication"); + // Reads client certificate and returns client + let certs: Vec<_> = { + let certs_path_str = path.display().to_string(); + let mut reader = BufReader::new(File::open(path).map_err(|e| { + io::Error::new( + e.kind(), + format!("Unable to load the client certificates [{certs_path_str}]: {e}"), + ) + })?); + rustls_pemfile::certs(&mut reader) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Unable to parse the client certificates"))? + } + .drain(..) + .map(Certificate) + .collect(); + Some(certs) + } else { + None + }; + + Ok(CertsAndKeys { + certs, + cert_keys, + client_ca_certs, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + #[tokio::test] + async fn read_server_crt_key_files() { + let tls_cert_path = "example-certs/server.crt"; + let tls_cert_key_path = "example-certs/server.key"; + let crypto_file_source = CryptoFileSourceBuilder::default() + .tls_cert_key_path(tls_cert_key_path) + .tls_cert_path(tls_cert_path) + .build(); + assert!(crypto_file_source.is_ok()); + + let crypto_file_source = crypto_file_source.unwrap(); + let crypto_elem = crypto_file_source.read().await; + assert!(crypto_elem.is_ok()); + } + + #[tokio::test] + async fn read_server_crt_key_files_with_client_ca_crt() { + let tls_cert_path = "example-certs/server.crt"; + let tls_cert_key_path = "example-certs/server.key"; + let client_ca_cert_path = Some("example-certs/client.ca.crt".to_string()); + let crypto_file_source = CryptoFileSourceBuilder::default() + .tls_cert_key_path(tls_cert_key_path) + .tls_cert_path(tls_cert_path) + .client_ca_cert_path(&client_ca_cert_path) + .build(); + assert!(crypto_file_source.is_ok()); + + let crypto_file_source = crypto_file_source.unwrap(); + let crypto_elem = crypto_file_source.read().await; + assert!(crypto_elem.is_ok()); + + let crypto_elem = crypto_elem.unwrap(); + assert!(crypto_elem.client_ca_certs.is_some()); + } +} diff --git a/src/cert_reader.rs b/src/cert_reader.rs deleted file mode 100644 index a52f2e2..0000000 --- a/src/cert_reader.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::{log::*, proxy::CertsAndKeys}; -use rustls::{Certificate, PrivateKey}; -use std::{ - fs::File, - io::{self, BufReader, Cursor, Read}, - path::PathBuf, -}; - -/// Read certificates and private keys from file -pub(crate) fn read_certs_and_keys( - cert_path: &PathBuf, - cert_key_path: &PathBuf, - client_ca_cert_path: Option<&PathBuf>, -) -> Result { - debug!("Read TLS server certificates and private key"); - - let certs: Vec<_> = { - let certs_path_str = cert_path.display().to_string(); - let mut reader = BufReader::new(File::open(cert_path).map_err(|e| { - io::Error::new( - e.kind(), - format!("Unable to load the certificates [{certs_path_str}]: {e}"), - ) - })?); - rustls_pemfile::certs(&mut reader) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Unable to parse the certificates"))? - } - .drain(..) - .map(Certificate) - .collect(); - - let cert_keys: Vec<_> = { - let cert_key_path_str = cert_key_path.display().to_string(); - let encoded_keys = { - let mut encoded_keys = vec![]; - File::open(cert_key_path) - .map_err(|e| { - io::Error::new( - e.kind(), - format!("Unable to load the certificate keys [{cert_key_path_str}]: {e}"), - ) - })? - .read_to_end(&mut encoded_keys)?; - encoded_keys - }; - let mut reader = Cursor::new(encoded_keys); - let pkcs8_keys = rustls_pemfile::pkcs8_private_keys(&mut reader).map_err(|_| { - io::Error::new( - io::ErrorKind::InvalidInput, - "Unable to parse the certificates private keys (PKCS8)", - ) - })?; - reader.set_position(0); - let mut rsa_keys = rustls_pemfile::rsa_private_keys(&mut reader)?; - let mut keys = pkcs8_keys; - keys.append(&mut rsa_keys); - if keys.is_empty() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "No private keys found - Make sure that they are in PKCS#8/PEM format", - )); - } - keys.drain(..).map(PrivateKey).collect() - }; - - let client_ca_certs = if let Some(path) = client_ca_cert_path { - debug!("Read CA certificates for client authentication"); - // Reads client certificate and returns client - let certs: Vec<_> = { - let certs_path_str = path.display().to_string(); - let mut reader = BufReader::new(File::open(path).map_err(|e| { - io::Error::new( - e.kind(), - format!("Unable to load the client certificates [{certs_path_str}]: {e}"), - ) - })?); - rustls_pemfile::certs(&mut reader) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Unable to parse the client certificates"))? - } - .drain(..) - .map(Certificate) - .collect(); - Some(certs) - } else { - None - }; - - Ok(CertsAndKeys { - certs, - cert_keys, - client_ca_certs, - }) -} diff --git a/src/certs.rs b/src/certs.rs new file mode 100644 index 0000000..2ed0198 --- /dev/null +++ b/src/certs.rs @@ -0,0 +1,22 @@ +use async_trait::async_trait; +use rustls::{Certificate, PrivateKey}; + +/// Certificates and private keys in rustls loaded from files +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct CertsAndKeys { + pub certs: Vec, + pub cert_keys: Vec, + pub client_ca_certs: Option>, +} + +#[async_trait] +// Trait to read certs and keys anywhere from KVS, file, sqlite, etc. +pub trait CryptoSource { + type Error; + + /// read crypto materials from source + async fn read(&self) -> Result; + + /// Returns true when mutual tls is enabled + fn is_mutual_tls(&self) -> bool; +} diff --git a/src/config/parse.rs b/src/config/parse.rs index 1593aba..1dc2545 100644 --- a/src/config/parse.rs +++ b/src/config/parse.rs @@ -1,9 +1,16 @@ use super::toml::ConfigToml; -use crate::{backend::Backends, error::*, globals::*, log::*, utils::BytesName}; +use crate::{ + backend::Backends, + cert_file_reader::CryptoFileSource, + error::{anyhow, ensure}, + globals::*, + log::*, + utils::BytesName, +}; use clap::Arg; use tokio::runtime::Handle; -pub fn build_globals(runtime_handle: Handle) -> std::result::Result { +pub fn build_globals(runtime_handle: Handle) -> std::result::Result, anyhow::Error> { let _ = include_str!("../../Cargo.toml"); let options = clap::command!().arg( Arg::new("config_file") @@ -72,7 +79,7 @@ pub fn build_globals(runtime_handle: Handle) -> std::result::Result for &ConfigToml { } impl ConfigToml { - pub fn new(config_file: &str) -> std::result::Result { - let config_str = fs::read_to_string(config_file).map_err(RpxyError::Io)?; + pub fn new(config_file: &str) -> std::result::Result { + let config_str = fs::read_to_string(config_file)?; - toml::from_str(&config_str).map_err(RpxyError::TomlDe) + toml::from_str(&config_str).map_err(|e| anyhow!(e)) } } -impl TryInto for &Application { +impl TryInto> for &Application { type Error = anyhow::Error; - fn try_into(self) -> std::result::Result { + fn try_into(self) -> std::result::Result, Self::Error> { let server_name_string = self.server_name.as_ref().ok_or(anyhow!("Missing server_name"))?; // backend builder @@ -199,11 +200,15 @@ impl TryInto for &Application { tls.https_redirection }; - backend_builder - .tls_cert_path(&tls.tls_cert_path) - .tls_cert_key_path(&tls.tls_cert_key_path) - .https_redirection(https_redirection) + let crypto_source = CryptoFileSourceBuilder::default() + .tls_cert_path(tls.tls_cert_path.as_ref().unwrap()) + .tls_cert_key_path(tls.tls_cert_key_path.as_ref().unwrap()) .client_ca_cert_path(&tls.client_ca_cert_path) + .build()?; + + backend_builder + .https_redirection(https_redirection) + .crypto_source(Some(crypto_source)) .build()? }; Ok(backend) @@ -251,7 +256,7 @@ impl TryInto for &Application { } impl TryInto for &UpstreamParams { - type Error = RpxyError; + type Error = anyhow::Error; fn try_into(self) -> std::result::Result { let scheme = match self.tls { diff --git a/src/error.rs b/src/error.rs index 18b4307..187c993 100644 --- a/src/error.rs +++ b/src/error.rs @@ -29,9 +29,8 @@ pub enum RpxyError { #[error("I/O Error")] Io(#[from] io::Error), - #[error("Toml Deserialization Error")] - TomlDe(#[from] toml::de::Error), - + // #[error("Toml Deserialization Error")] + // TomlDe(#[from] toml::de::Error), #[cfg(feature = "http3")] #[error("Quic Connection Error")] QuicConn(#[from] quinn::ConnectionError), diff --git a/src/globals.rs b/src/globals.rs index 64f9d8d..b85733b 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -1,3 +1,4 @@ +use crate::certs::CryptoSource; use crate::{backend::Backends, constants::*}; use std::net::SocketAddr; use std::sync::{ @@ -8,12 +9,15 @@ use tokio::time::Duration; /// Global object containing proxy configurations and shared object like counters. /// But note that in Globals, we do not have Mutex and RwLock. It is indeed, the context shared among async tasks. -pub struct Globals { +pub struct Globals +where + T: CryptoSource, +{ /// Configuration parameters for proxy transport and request handlers pub proxy_config: ProxyConfig, // TODO: proxy configはarcに包んでこいつだけ使いまわせばいいように変えていく。backendsも? /// Backend application objects to which http request handler forward incoming requests - pub backends: Backends, + pub backends: Backends, /// Shared context - Counter for serving requests pub request_count: RequestCount, diff --git a/src/handler/handler_main.rs b/src/handler/handler_main.rs index d2a47be..c23fd24 100644 --- a/src/handler/handler_main.rs +++ b/src/handler/handler_main.rs @@ -2,6 +2,7 @@ use super::{utils_headers::*, utils_request::*, utils_synth_response::*, HandlerContext}; use crate::{ backend::{Backend, UpstreamGroup}, + certs::CryptoSource, error::*, globals::Globals, log::*, @@ -18,17 +19,19 @@ use std::{env, net::SocketAddr, sync::Arc}; use tokio::{io::copy_bidirectional, time::timeout}; #[derive(Clone, Builder)] -pub struct HttpMessageHandler +pub struct HttpMessageHandler where T: Connect + Clone + Sync + Send + 'static, + U: CryptoSource + Clone, { forwarder: Arc>, - globals: Arc, + globals: Arc>, } -impl HttpMessageHandler +impl HttpMessageHandler where T: Connect + Clone + Sync + Send + 'static, + U: CryptoSource + Clone, { fn return_with_error_log(&self, status_code: StatusCode, log_data: &mut MessageLog) -> Result> { log_data.status_code(&status_code).output(); @@ -194,11 +197,10 @@ where //////////////////////////////////////////////////// // Functions to generate messages - fn generate_response_forwarded( - &self, - response: &mut Response, - chosen_backend: &Backend, - ) -> Result<()> { + fn generate_response_forwarded(&self, response: &mut Response, chosen_backend: &Backend) -> Result<()> + where + B: core::fmt::Debug, + { let headers = response.headers_mut(); remove_connection_header(headers); remove_hop_header(headers); @@ -207,7 +209,12 @@ where #[cfg(feature = "http3")] { // TODO: Workaround for avoid h3 for client authentication - if self.globals.proxy_config.http3 && chosen_backend.client_ca_cert_path.is_none() { + if self.globals.proxy_config.http3 + && chosen_backend + .crypto_source + .as_ref() + .is_some_and(|v| !v.is_mutual_tls()) + { if let Some(port) = self.globals.proxy_config.https_port { add_header_entry_overwrite_if_exist( headers, diff --git a/src/main.rs b/src/main.rs index ea47e57..7f8dcfc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use certs::CryptoSource; #[cfg(not(target_env = "msvc"))] use tikv_jemallocator::Jemalloc; @@ -6,7 +7,8 @@ use tikv_jemallocator::Jemalloc; static GLOBAL: Jemalloc = Jemalloc; mod backend; -mod cert_reader; +mod cert_file_reader; +mod certs; mod config; mod constants; mod error; @@ -17,7 +19,8 @@ mod proxy; mod utils; use crate::{ - config::build_globals, error::*, globals::*, handler::HttpMessageHandlerBuilder, log::*, proxy::ProxyBuilder, + cert_file_reader::CryptoFileSource, config::build_globals, error::*, globals::*, handler::HttpMessageHandlerBuilder, + log::*, proxy::ProxyBuilder, }; use futures::future::select_all; use hyper::Client; @@ -33,7 +36,7 @@ fn main() { let runtime = runtime_builder.build().unwrap(); runtime.block_on(async { - let globals = match build_globals(runtime.handle().clone()) { + let globals: Globals = match build_globals(runtime.handle().clone()) { Ok(g) => g, Err(e) => { error!("Invalid configuration: {}", e); @@ -47,7 +50,10 @@ fn main() { } // entrypoint creates and spawns tasks of proxy services -async fn entrypoint(globals: Arc) -> Result<()> { +async fn entrypoint(globals: Arc>) -> Result<()> +where + T: CryptoSource + Clone + Send + Sync + 'static, +{ // let connector = TrustDnsResolver::default().into_rustls_webpki_https_connector(); let connector = hyper_rustls::HttpsConnectorBuilder::new() .with_webpki_roots() diff --git a/src/proxy/crypto_service.rs b/src/proxy/crypto_service.rs index 728a531..8d7f00d 100644 --- a/src/proxy/crypto_service.rs +++ b/src/proxy/crypto_service.rs @@ -1,5 +1,5 @@ use crate::{ - cert_reader::read_certs_and_keys, // TODO: Trait defining read_certs_and_keys and add struct implementing the trait to backend when build backend + certs::{CertsAndKeys, CryptoSource}, globals::Globals, log::*, utils::ServerNameBytesExp, @@ -10,23 +10,18 @@ use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; use rustls::{ server::ResolvesServerCertUsingSni, sign::{any_supported_type, CertifiedKey}, - Certificate, OwnedTrustAnchor, PrivateKey, RootCertStore, ServerConfig, + OwnedTrustAnchor, RootCertStore, ServerConfig, }; use std::{io, sync::Arc}; use x509_parser::prelude::*; #[derive(Clone)] /// Reloader service for certificates and keys for TLS -pub struct CryptoReloader { - globals: Arc, -} - -/// Certificates and private keys in rustls loaded from files -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct CertsAndKeys { - pub certs: Vec, - pub cert_keys: Vec, - pub client_ca_certs: Option>, +pub struct CryptoReloader +where + T: CryptoSource, +{ + globals: Arc>, } pub type SniServerCryptoMap = HashMap>; @@ -44,8 +39,11 @@ pub struct ServerCryptoBase { } #[async_trait] -impl Reload for CryptoReloader { - type Source = Arc; +impl Reload for CryptoReloader +where + T: CryptoSource + Sync + Send, +{ + type Source = Arc>; async fn new(source: &Self::Source) -> Result> { Ok(Self { globals: source.clone(), @@ -56,13 +54,11 @@ impl Reload for CryptoReloader { let mut certs_and_keys_map = ServerCryptoBase::default(); for (server_name_bytes_exp, backend) in self.globals.backends.apps.iter() { - if backend.tls_cert_key_path.is_some() && backend.tls_cert_path.is_some() { - let tls_cert_key_path = backend.tls_cert_key_path.as_ref().unwrap(); - let tls_cert_path = backend.tls_cert_path.as_ref().unwrap(); - let tls_client_ca_cert_path = backend.client_ca_cert_path.as_ref(); - let certs_and_keys = read_certs_and_keys(tls_cert_path, tls_cert_key_path, tls_client_ca_cert_path) + if let Some(crypto_source) = &backend.crypto_source { + let certs_and_keys = crypto_source + .read() + .await .map_err(|_e| ReloaderError::::Reload("Failed to reload cert, key or ca cert"))?; - certs_and_keys_map .inner .insert(server_name_bytes_exp.to_owned(), certs_and_keys); diff --git a/src/proxy/mod.rs b/src/proxy/mod.rs index d8fdc83..73a4002 100644 --- a/src/proxy/mod.rs +++ b/src/proxy/mod.rs @@ -5,5 +5,4 @@ mod proxy_h3; mod proxy_main; mod proxy_tls; -pub use crypto_service::CertsAndKeys; pub use proxy_main::{Proxy, ProxyBuilder, ProxyBuilderError}; diff --git a/src/proxy/proxy_h3.rs b/src/proxy/proxy_h3.rs index 12ebd7d..324060f 100644 --- a/src/proxy/proxy_h3.rs +++ b/src/proxy/proxy_h3.rs @@ -1,14 +1,15 @@ use super::Proxy; -use crate::{error::*, log::*, utils::ServerNameBytesExp}; +use crate::{certs::CryptoSource, error::*, log::*, utils::ServerNameBytesExp}; use bytes::{Buf, Bytes}; use h3::{quic::BidiStream, server::RequestStream}; use hyper::{client::connect::Connect, Body, Request, Response}; use std::net::SocketAddr; use tokio::time::{timeout, Duration}; -impl Proxy +impl Proxy where T: Connect + Clone + Sync + Send + 'static, + U: CryptoSource + Clone + Sync + Send + 'static, { pub(super) async fn connection_serve_h3( self, diff --git a/src/proxy/proxy_main.rs b/src/proxy/proxy_main.rs index a0f9660..e5a02a5 100644 --- a/src/proxy/proxy_main.rs +++ b/src/proxy/proxy_main.rs @@ -1,5 +1,7 @@ // use super::proxy_handler::handle_request; -use crate::{error::*, globals::Globals, handler::HttpMessageHandler, log::*, utils::ServerNameBytesExp}; +use crate::{ + certs::CryptoSource, error::*, globals::Globals, handler::HttpMessageHandler, log::*, utils::ServerNameBytesExp, +}; use derive_builder::{self, Builder}; use hyper::{client::connect::Connect, server::conn::Http, service::service_fn, Body, Request}; use std::{net::SocketAddr, sync::Arc}; @@ -32,19 +34,21 @@ where } #[derive(Clone, Builder)] -pub struct Proxy +pub struct Proxy where T: Connect + Clone + Sync + Send + 'static, + U: CryptoSource + Clone + Sync + Send + 'static, { pub listening_on: SocketAddr, pub tls_enabled: bool, // TCP待受がTLSかどうか - pub msg_handler: HttpMessageHandler, - pub globals: Arc, + pub msg_handler: HttpMessageHandler, + pub globals: Arc>, } -impl Proxy +impl Proxy where T: Connect + Clone + Sync + Send + 'static, + U: CryptoSource + Clone + Sync + Send, { pub(super) fn client_serve( self, diff --git a/src/proxy/proxy_tls.rs b/src/proxy/proxy_tls.rs index e01f9d3..5e846f0 100644 --- a/src/proxy/proxy_tls.rs +++ b/src/proxy/proxy_tls.rs @@ -2,7 +2,7 @@ use super::{ crypto_service::{CryptoReloader, ServerCrypto, ServerCryptoBase, SniServerCryptoMap}, proxy_main::{LocalExecutor, Proxy}, }; -use crate::{constants::*, error::*, log::*, utils::BytesName}; +use crate::{certs::CryptoSource, constants::*, error::*, log::*, utils::BytesName}; use hot_reload::{ReloaderReceiver, ReloaderService}; use hyper::{client::connect::Connect, server::conn::Http}; #[cfg(feature = "http3")] @@ -15,9 +15,10 @@ use tokio::{ time::{timeout, Duration}, }; -impl Proxy +impl Proxy where T: Connect + Clone + Sync + Send + 'static, + U: CryptoSource + Clone + Sync + Send + 'static, { // TCP Listener Service, i.e., http/2 and http/1.1 async fn listener_service( @@ -181,7 +182,7 @@ where } pub async fn start_with_tls(self, server: Http) -> Result<()> { - let (cert_reloader_service, cert_reloader_rx) = ReloaderService::::new( + let (cert_reloader_service, cert_reloader_rx) = ReloaderService::, ServerCryptoBase>::new( &self.globals.clone(), CERTS_WATCH_DELAY_SECS, !LOAD_CERTS_ONLY_WHEN_UPDATED,