chore: add tls log (#357)

This commit is contained in:
houseme
2025-08-07 17:33:57 +08:00
committed by GitHub
parent c42fbed3d2
commit 130f85a575
4 changed files with 86 additions and 69 deletions

1
.gitignore vendored
View File

@@ -20,3 +20,4 @@ profile.json
.docker/openobserve-otel/data
*.zst
.secrets
*.go

56
Cargo.lock generated
View File

@@ -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",

View File

@@ -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 }

View File

@@ -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<Option<TlsAcceptor>> {
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");