14
14
15
15
// Ensure the correct path for parse_license is imported
16
16
use crate :: admin;
17
- // use crate::admin::console::{CONSOLE_CONFIG, init_console_cfg};
18
17
use crate :: auth:: IAMAuth ;
19
18
use crate :: config;
20
19
use crate :: server:: hybrid:: hybrid;
@@ -43,8 +42,6 @@ use std::net::SocketAddr;
43
42
use std:: sync:: Arc ;
44
43
use std:: time:: Duration ;
45
44
use tokio:: net:: { TcpListener , TcpStream } ;
46
- #[ cfg( unix) ]
47
- use tokio:: signal:: unix:: { SignalKind , signal} ;
48
45
use tokio_rustls:: TlsAcceptor ;
49
46
use tonic:: { Request , Status , metadata:: MetadataValue } ;
50
47
use tower:: ServiceBuilder ;
@@ -172,6 +169,7 @@ pub async fn start_http_server(
172
169
tokio:: spawn ( async move {
173
170
#[ cfg( unix) ]
174
171
let ( mut sigterm_inner, mut sigint_inner) = {
172
+ use tokio:: signal:: unix:: { SignalKind , signal} ;
175
173
// Unix platform specific code
176
174
let sigterm_inner = signal ( SignalKind :: terminate ( ) ) . expect ( "Failed to create SIGTERM signal handler" ) ;
177
175
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>> {
292
290
293
291
debug ! ( "Found TLS directory, checking for certificates" ) ;
294
292
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)
296
297
if let Ok ( cert_key_pairs) = rustfs_utils:: load_all_certs_from_directory ( tls_path) {
297
298
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
300
305
let mut server_config = ServerConfig :: builder ( )
301
306
. 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
303
310
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
+
304
315
return Ok ( Some ( TlsAcceptor :: from ( Arc :: new ( server_config) ) ) ) ;
305
316
}
306
317
}
307
318
308
- // 2. Fallback to legacy single certificate mode
319
+ // 2. Revert to the traditional single- certificate mode
309
320
let key_path = format ! ( "{tls_path}/{RUSTFS_TLS_KEY}" ) ;
310
321
let cert_path = format ! ( "{tls_path}/{RUSTFS_TLS_CERT}" ) ;
311
322
if tokio:: try_join!( tokio:: fs:: metadata( & key_path) , tokio:: fs:: metadata( & cert_path) ) . is_ok ( ) {
312
323
debug ! ( "Found legacy single TLS certificate, starting with HTTPS" ) ;
313
- let _ = rustls:: crypto:: aws_lc_rs:: default_provider ( ) . install_default ( ) ;
314
324
let certs = rustfs_utils:: load_certs ( & cert_path) . map_err ( |e| rustfs_utils:: certs_error ( e. to_string ( ) ) ) ?;
315
325
let key = rustfs_utils:: load_private_key ( & key_path) . map_err ( |e| rustfs_utils:: certs_error ( e. to_string ( ) ) ) ?;
326
+
316
327
let mut server_config = ServerConfig :: builder ( )
317
328
. with_no_client_auth ( )
318
329
. with_single_cert ( certs, key)
319
330
. map_err ( |e| rustfs_utils:: certs_error ( e. to_string ( ) ) ) ?;
331
+
332
+ // Configure ALPN protocol priority
320
333
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
+
321
338
return Ok ( Some ( TlsAcceptor :: from ( Arc :: new ( server_config) ) ) ) ;
322
339
}
323
340
@@ -398,6 +415,10 @@ fn process_connection(
398
415
// Decide whether to handle HTTPS or HTTP connections based on the existence of TLS Acceptor
399
416
if let Some ( acceptor) = tls_acceptor {
400
417
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 ( ) ) ;
401
422
match acceptor. accept ( socket) . await {
402
423
Ok ( tls_socket) => {
403
424
debug ! ( "TLS handshake successful" ) ;
@@ -408,8 +429,56 @@ fn process_connection(
408
429
}
409
430
}
410
431
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
413
482
}
414
483
}
415
484
debug ! ( "TLS handshake success" ) ;
0 commit comments