mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 01:30:33 +00:00
chore: add tls log (#357)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -20,3 +20,4 @@ profile.json
|
||||
.docker/openobserve-otel/data
|
||||
*.zst
|
||||
.secrets
|
||||
*.go
|
||||
56
Cargo.lock
generated
56
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user