From 8115bbf8661d14e0d819fc65636f6ad69938ca1c Mon Sep 17 00:00:00 2001 From: Jun Kurihara Date: Tue, 11 Oct 2022 16:17:50 +0900 Subject: [PATCH] refactor --- Cargo.toml | 2 +- src/proxy/proxy_client_cert.rs | 4 +-- src/proxy/proxy_tls.rs | 62 +++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 965c9f9..7f16166 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ http3 = ["quinn", "h3", "h3-quinn"] [dependencies] env_logger = "0.9.1" anyhow = "1.0.65" -clap = { version = "4.0.10", features = ["std", "cargo", "wrap_help"] } +clap = { version = "4.0.12", features = ["std", "cargo", "wrap_help"] } futures = { version = "0.3.24", features = ["alloc", "async-await"] } hyper = { version = "0.14.20", default-features = false, features = [ "server", diff --git a/src/proxy/proxy_client_cert.rs b/src/proxy/proxy_client_cert.rs index a0f5faf..c77b0f9 100644 --- a/src/proxy/proxy_client_cert.rs +++ b/src/proxy/proxy_client_cert.rs @@ -46,9 +46,9 @@ pub(super) fn check_client_authentication( if !match_server_crypto_and_client_cert { // TODO: return 403 here - error!("Inconsistent client certificate for given server name"); + error!("Inconsistent client certificate was provided for SNI"); return Err(RpxyError::Proxy( - "Inconsistent client certificate for given server name".to_string(), + "Inconsistent client certificate was provided for SNI".to_string(), )); } diff --git a/src/proxy/proxy_tls.rs b/src/proxy/proxy_tls.rs index 8a71491..153c6cd 100644 --- a/src/proxy/proxy_tls.rs +++ b/src/proxy/proxy_tls.rs @@ -70,40 +70,46 @@ where // spawns async handshake to avoid blocking thread by sequential handshake. let handshake_fut = async move { // timeout is introduced to avoid get stuck here. - match timeout(Duration::from_secs(TLS_HANDSHAKE_TIMEOUT_SEC), acceptor.accept(raw_stream)).await { - Ok(x) => match x { - Ok(stream) => { - // Retrieve SNI - let (_, conn) = stream.get_ref(); - let server_name = conn.sni_hostname(); - debug!("HTTP/2 or 1.1: SNI in ClientHello: {:?}", server_name); - let server_name = server_name.map_or_else(|| None, |v| Some(v.to_server_name_vec())); - if server_name.is_none(){ - Err(RpxyError::Proxy("No SNI is given".to_string())) - } else { - ////////////////////////////// - // Check client certificate - // TODO: consider move this function to the layer of handle_request (L7) to return 403 - let client_certs = conn.peer_certificates(); - let client_certs_setting_for_sni = sni_cc_map.get(&server_name.clone().unwrap()); - check_client_authentication(client_certs, client_certs_setting_for_sni)?; - ////////////////////////////// - // this immediately spawns another future to actually handle stream. so it is okay to introduce timeout for handshake. - self_inner.client_serve(stream, server_clone, client_addr, server_name); // TODO: don't want to pass copied value... - Ok(()) - } - }, - Err(e) => { - Err(RpxyError::Proxy(format!("Failed to handshake TLS: {}", e))) - } - }, + let accepted = match timeout(Duration::from_secs(TLS_HANDSHAKE_TIMEOUT_SEC), acceptor.accept(raw_stream)).await { + Ok(a) => a, Err(e) => { - Err(RpxyError::Proxy(format!("Timeout to handshake TLS: {}", e))) + return Err(RpxyError::Proxy(format!("Timeout to handshake TLS: {}", e))); } + }; + let stream = match accepted { + Ok(s) => s, + Err(e) => { + return Err(RpxyError::Proxy(format!("Failed to handshake TLS: {}", e))); + } + }; + // Retrieve SNI + let (_, conn) = stream.get_ref(); + let server_name = conn.sni_hostname(); + debug!("HTTP/2 or 1.1: SNI in ClientHello: {:?}", server_name); + let server_name = server_name.map_or_else(|| None, |v| Some(v.to_server_name_vec())); + if server_name.is_none(){ + // conn.send_close_notify(); + Err(RpxyError::Proxy("No SNI is given".to_string())) + } else { + ////////////////////////////// + // Check client certificate + // TODO: consider move this function to the layer of handle_request (L7) to return 403 + let client_certs = conn.peer_certificates(); + let client_certs_setting_for_sni = sni_cc_map.get(&server_name.clone().unwrap()); + check_client_authentication(client_certs, client_certs_setting_for_sni)?; + // if let Err(e) = check_client_authentication(client_certs, client_certs_setting_for_sni){ + // conn.send_close_notify(); + // return Err(e); + // } + ////////////////////////////// + // this immediately spawns another future to actually handle stream. so it is okay to introduce timeout for handshake. + self_inner.client_serve(stream, server_clone, client_addr, server_name); // TODO: don't want to pass copied value... + Ok(()) } }; self.globals.runtime_handle.spawn( async move { if let Err(e) = handshake_fut.await { + error!("{}", e); } });