From 130f85a57533fb0ddff690071af50f7fd6e2465b Mon Sep 17 00:00:00 2001 From: houseme Date: Thu, 7 Aug 2025 17:33:57 +0800 Subject: [PATCH] chore: add tls log (#357) --- .gitignore | 1 + Cargo.lock | 56 ------------------------ rustfs/Cargo.toml | 7 ++- rustfs/src/server/http.rs | 91 ++++++++++++++++++++++++++++++++++----- 4 files changed, 86 insertions(+), 69 deletions(-) diff --git a/.gitignore b/.gitignore index dbf4271a..cb7502bf 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ profile.json .docker/openobserve-otel/data *.zst .secrets +*.go \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index b2c27f5a..43157a85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1155,50 +1155,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "axum-extra" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d" -dependencies = [ - "axum", - "axum-core", - "bytes", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "serde", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-server" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495c05f60d6df0093e8fb6e74aa5846a0ad06abaf96d76166283720bf740f8ab" -dependencies = [ - "arc-swap", - "bytes", - "fs-err", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.6.0", - "hyper-util", - "pin-project-lite", - "rustls 0.23.31", - "rustls-pemfile 2.2.0", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.2", - "tower-service", -] - [[package]] name = "backtrace" version = "0.3.75" @@ -3970,16 +3926,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs-err" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7be93788013f265201256d58f04936a8079ad5dc898743aa20525f503b683" -dependencies = [ - "autocfg", - "tokio", -] - [[package]] name = "fs_extra" version = "1.3.0" @@ -8105,8 +8051,6 @@ dependencies = [ "atoi", "atomic_enum", "axum", - "axum-extra", - "axum-server", "bytes", "chrono", "clap", diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index b13ed45b..db51a8e6 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -33,6 +33,11 @@ path = "src/main.rs" [lints] workspace = true +[features] +default = [] +tls_fallback = [] +full = ["tls_fallback"] + [dependencies] rustfs-ahm = { workspace = true } rustfs-zip = { workspace = true } @@ -54,8 +59,6 @@ rustfs-s3select-query = { workspace = true } atoi = { workspace = true } atomic_enum = { workspace = true } axum.workspace = true -axum-extra = { workspace = true } -axum-server = { workspace = true } async-trait = { workspace = true } bytes = { workspace = true } chrono = { workspace = true } diff --git a/rustfs/src/server/http.rs b/rustfs/src/server/http.rs index 1beef881..70ba5c38 100644 --- a/rustfs/src/server/http.rs +++ b/rustfs/src/server/http.rs @@ -14,7 +14,6 @@ // Ensure the correct path for parse_license is imported use crate::admin; -// use crate::admin::console::{CONSOLE_CONFIG, init_console_cfg}; use crate::auth::IAMAuth; use crate::config; use crate::server::hybrid::hybrid; @@ -43,8 +42,6 @@ use std::net::SocketAddr; use std::sync::Arc; use std::time::Duration; use tokio::net::{TcpListener, TcpStream}; -#[cfg(unix)] -use tokio::signal::unix::{SignalKind, signal}; use tokio_rustls::TlsAcceptor; use tonic::{Request, Status, metadata::MetadataValue}; use tower::ServiceBuilder; @@ -172,6 +169,7 @@ pub async fn start_http_server( tokio::spawn(async move { #[cfg(unix)] let (mut sigterm_inner, mut sigint_inner) = { + use tokio::signal::unix::{SignalKind, signal}; // Unix platform specific code let sigterm_inner = signal(SignalKind::terminate()).expect("Failed to create SIGTERM signal handler"); let sigint_inner = signal(SignalKind::interrupt()).expect("Failed to create SIGINT signal handler"); @@ -292,32 +290,51 @@ async fn setup_tls_acceptor(tls_path: &str) -> Result> { debug!("Found TLS directory, checking for certificates"); - // 1. Try to load all certificates from the directory (multi-cert support) + // Make sure to use a modern encryption suite + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + + // 1. Attempt to load all certificates in the directory (multi-certificate support, for SNI) if let Ok(cert_key_pairs) = rustfs_utils::load_all_certs_from_directory(tls_path) { if !cert_key_pairs.is_empty() { - debug!("Found {} certificates, creating multi-cert resolver", cert_key_pairs.len()); - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + debug!("Found {} certificates, creating SNI-aware multi-cert resolver", cert_key_pairs.len()); + + // Create an SNI-enabled certificate resolver + let resolver = rustfs_utils::create_multi_cert_resolver(cert_key_pairs)?; + + // Configure the server to enable SNI support let mut server_config = ServerConfig::builder() .with_no_client_auth() - .with_cert_resolver(Arc::new(rustfs_utils::create_multi_cert_resolver(cert_key_pairs)?)); + .with_cert_resolver(Arc::new(resolver)); + + // Configure ALPN protocol priority server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; + + // Log SNI requests + server_config.key_log = Arc::new(rustls::KeyLogFile::new()); + return Ok(Some(TlsAcceptor::from(Arc::new(server_config)))); } } - // 2. Fallback to legacy single certificate mode + // 2. Revert to the traditional single-certificate mode let key_path = format!("{tls_path}/{RUSTFS_TLS_KEY}"); let cert_path = format!("{tls_path}/{RUSTFS_TLS_CERT}"); if tokio::try_join!(tokio::fs::metadata(&key_path), tokio::fs::metadata(&cert_path)).is_ok() { debug!("Found legacy single TLS certificate, starting with HTTPS"); - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); let certs = rustfs_utils::load_certs(&cert_path).map_err(|e| rustfs_utils::certs_error(e.to_string()))?; let key = rustfs_utils::load_private_key(&key_path).map_err(|e| rustfs_utils::certs_error(e.to_string()))?; + let mut server_config = ServerConfig::builder() .with_no_client_auth() .with_single_cert(certs, key) .map_err(|e| rustfs_utils::certs_error(e.to_string()))?; + + // Configure ALPN protocol priority server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; + + // Log SNI requests + server_config.key_log = Arc::new(rustls::KeyLogFile::new()); + return Ok(Some(TlsAcceptor::from(Arc::new(server_config)))); } @@ -398,6 +415,10 @@ fn process_connection( // Decide whether to handle HTTPS or HTTP connections based on the existence of TLS Acceptor if let Some(acceptor) = tls_acceptor { debug!("TLS handshake start"); + let peer_addr = socket + .peer_addr() + .ok() + .map_or_else(|| "unknown".to_string(), |addr| addr.to_string()); match acceptor.accept(socket).await { Ok(tls_socket) => { debug!("TLS handshake successful"); @@ -408,8 +429,56 @@ fn process_connection( } } Err(err) => { - error!(?err, "TLS handshake failed"); - return; // Failed to end the task directly + // Detailed analysis of the reasons why the TLS handshake fails + let err_str = err.to_string(); + if err_str.contains("unexpected EOF") || err_str.contains("handshake eof") { + info!( peer_addr = %peer_addr,"TLS handshake failed with EOF, attempting fallback to HTTP: {}", err); + + // Try falling back the connection to HTTP mode (this feature is only enabled in specific environments) + #[cfg(feature = "tls_fallback")] + { + // Since the original connection has been consumed, a new connection needs to be accepted + match TcpStream::connect(peer_addr.clone()).await { + Ok(new_socket) => { + debug!("Successfully reconnected to client for HTTP fallback"); + let stream = TokioIo::new(new_socket); + let conn = http_server.serve_connection(stream, hybrid_service); + if let Err(err) = graceful.watch(conn).await { + handle_connection_error(&*err); + } + return; + } + Err(e) => { + error!("Failed to reconnect for HTTP fallback: {}", e); + } + } + } + } else if err_str.contains("protocol version") { + error!( + peer_addr = %peer_addr, + "TLS handshake failed due to protocol version mismatch: {}", err + ); + } else if err_str.contains("certificate") { + error!( + peer_addr = %peer_addr, + "TLS handshake failed due to certificate issues: {}", err + ); + } else { + error!( + peer_addr = %peer_addr, + "TLS handshake failed: {}", err + ); + } + + // Record detailed diagnostic information + debug!( + peer_addr = %peer_addr, + error_type = %std::any::type_name_of_val(&err), + error_details = %err, + "TLS handshake failure details" + ); + + return; // End the mission } } debug!("TLS handshake success");