Skip to content

Commit 130f85a

Browse files
authored
chore: add tls log (#357)
1 parent c42fbed commit 130f85a

File tree

4 files changed

+86
-69
lines changed

4 files changed

+86
-69
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ profile.json
2020
.docker/openobserve-otel/data
2121
*.zst
2222
.secrets
23+
*.go

Cargo.lock

Lines changed: 0 additions & 56 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustfs/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ path = "src/main.rs"
3333
[lints]
3434
workspace = true
3535

36+
[features]
37+
default = []
38+
tls_fallback = []
39+
full = ["tls_fallback"]
40+
3641
[dependencies]
3742
rustfs-ahm = { workspace = true }
3843
rustfs-zip = { workspace = true }
@@ -54,8 +59,6 @@ rustfs-s3select-query = { workspace = true }
5459
atoi = { workspace = true }
5560
atomic_enum = { workspace = true }
5661
axum.workspace = true
57-
axum-extra = { workspace = true }
58-
axum-server = { workspace = true }
5962
async-trait = { workspace = true }
6063
bytes = { workspace = true }
6164
chrono = { workspace = true }

rustfs/src/server/http.rs

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
// Ensure the correct path for parse_license is imported
1616
use crate::admin;
17-
// use crate::admin::console::{CONSOLE_CONFIG, init_console_cfg};
1817
use crate::auth::IAMAuth;
1918
use crate::config;
2019
use crate::server::hybrid::hybrid;
@@ -43,8 +42,6 @@ use std::net::SocketAddr;
4342
use std::sync::Arc;
4443
use std::time::Duration;
4544
use tokio::net::{TcpListener, TcpStream};
46-
#[cfg(unix)]
47-
use tokio::signal::unix::{SignalKind, signal};
4845
use tokio_rustls::TlsAcceptor;
4946
use tonic::{Request, Status, metadata::MetadataValue};
5047
use tower::ServiceBuilder;
@@ -172,6 +169,7 @@ pub async fn start_http_server(
172169
tokio::spawn(async move {
173170
#[cfg(unix)]
174171
let (mut sigterm_inner, mut sigint_inner) = {
172+
use tokio::signal::unix::{SignalKind, signal};
175173
// Unix platform specific code
176174
let sigterm_inner = signal(SignalKind::terminate()).expect("Failed to create SIGTERM signal handler");
177175
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>> {
292290

293291
debug!("Found TLS directory, checking for certificates");
294292

295-
// 1. Try to load all certificates from the directory (multi-cert support)
293+
// Make sure to use a modern encryption suite
294+
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
295+
296+
// 1. Attempt to load all certificates in the directory (multi-certificate support, for SNI)
296297
if let Ok(cert_key_pairs) = rustfs_utils::load_all_certs_from_directory(tls_path) {
297298
if !cert_key_pairs.is_empty() {
298-
debug!("Found {} certificates, creating multi-cert resolver", cert_key_pairs.len());
299-
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
299+
debug!("Found {} certificates, creating SNI-aware multi-cert resolver", cert_key_pairs.len());
300+
301+
// Create an SNI-enabled certificate resolver
302+
let resolver = rustfs_utils::create_multi_cert_resolver(cert_key_pairs)?;
303+
304+
// Configure the server to enable SNI support
300305
let mut server_config = ServerConfig::builder()
301306
.with_no_client_auth()
302-
.with_cert_resolver(Arc::new(rustfs_utils::create_multi_cert_resolver(cert_key_pairs)?));
307+
.with_cert_resolver(Arc::new(resolver));
308+
309+
// Configure ALPN protocol priority
303310
server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()];
311+
312+
// Log SNI requests
313+
server_config.key_log = Arc::new(rustls::KeyLogFile::new());
314+
304315
return Ok(Some(TlsAcceptor::from(Arc::new(server_config))));
305316
}
306317
}
307318

308-
// 2. Fallback to legacy single certificate mode
319+
// 2. Revert to the traditional single-certificate mode
309320
let key_path = format!("{tls_path}/{RUSTFS_TLS_KEY}");
310321
let cert_path = format!("{tls_path}/{RUSTFS_TLS_CERT}");
311322
if tokio::try_join!(tokio::fs::metadata(&key_path), tokio::fs::metadata(&cert_path)).is_ok() {
312323
debug!("Found legacy single TLS certificate, starting with HTTPS");
313-
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
314324
let certs = rustfs_utils::load_certs(&cert_path).map_err(|e| rustfs_utils::certs_error(e.to_string()))?;
315325
let key = rustfs_utils::load_private_key(&key_path).map_err(|e| rustfs_utils::certs_error(e.to_string()))?;
326+
316327
let mut server_config = ServerConfig::builder()
317328
.with_no_client_auth()
318329
.with_single_cert(certs, key)
319330
.map_err(|e| rustfs_utils::certs_error(e.to_string()))?;
331+
332+
// Configure ALPN protocol priority
320333
server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()];
334+
335+
// Log SNI requests
336+
server_config.key_log = Arc::new(rustls::KeyLogFile::new());
337+
321338
return Ok(Some(TlsAcceptor::from(Arc::new(server_config))));
322339
}
323340

@@ -398,6 +415,10 @@ fn process_connection(
398415
// Decide whether to handle HTTPS or HTTP connections based on the existence of TLS Acceptor
399416
if let Some(acceptor) = tls_acceptor {
400417
debug!("TLS handshake start");
418+
let peer_addr = socket
419+
.peer_addr()
420+
.ok()
421+
.map_or_else(|| "unknown".to_string(), |addr| addr.to_string());
401422
match acceptor.accept(socket).await {
402423
Ok(tls_socket) => {
403424
debug!("TLS handshake successful");
@@ -408,8 +429,56 @@ fn process_connection(
408429
}
409430
}
410431
Err(err) => {
411-
error!(?err, "TLS handshake failed");
412-
return; // Failed to end the task directly
432+
// Detailed analysis of the reasons why the TLS handshake fails
433+
let err_str = err.to_string();
434+
if err_str.contains("unexpected EOF") || err_str.contains("handshake eof") {
435+
info!( peer_addr = %peer_addr,"TLS handshake failed with EOF, attempting fallback to HTTP: {}", err);
436+
437+
// Try falling back the connection to HTTP mode (this feature is only enabled in specific environments)
438+
#[cfg(feature = "tls_fallback")]
439+
{
440+
// Since the original connection has been consumed, a new connection needs to be accepted
441+
match TcpStream::connect(peer_addr.clone()).await {
442+
Ok(new_socket) => {
443+
debug!("Successfully reconnected to client for HTTP fallback");
444+
let stream = TokioIo::new(new_socket);
445+
let conn = http_server.serve_connection(stream, hybrid_service);
446+
if let Err(err) = graceful.watch(conn).await {
447+
handle_connection_error(&*err);
448+
}
449+
return;
450+
}
451+
Err(e) => {
452+
error!("Failed to reconnect for HTTP fallback: {}", e);
453+
}
454+
}
455+
}
456+
} else if err_str.contains("protocol version") {
457+
error!(
458+
peer_addr = %peer_addr,
459+
"TLS handshake failed due to protocol version mismatch: {}", err
460+
);
461+
} else if err_str.contains("certificate") {
462+
error!(
463+
peer_addr = %peer_addr,
464+
"TLS handshake failed due to certificate issues: {}", err
465+
);
466+
} else {
467+
error!(
468+
peer_addr = %peer_addr,
469+
"TLS handshake failed: {}", err
470+
);
471+
}
472+
473+
// Record detailed diagnostic information
474+
debug!(
475+
peer_addr = %peer_addr,
476+
error_type = %std::any::type_name_of_val(&err),
477+
error_details = %err,
478+
"TLS handshake failure details"
479+
);
480+
481+
return; // End the mission
413482
}
414483
}
415484
debug!("TLS handshake success");

0 commit comments

Comments
 (0)