@@ -566,7 +566,8 @@ async fn handle_tunnel_connection(
566566 protocol_id. as_str ( ) == "dns" || // DNS over TLS
567567 protocol_id. as_str ( ) == "dns-google" ;
568568
569- if config. detection . enable_tls_session_emulation && is_tls_protocol {
569+ let use_tls_emulation = config. detection . enable_tls_session_emulation && is_tls_protocol;
570+ if use_tls_emulation {
570571 noise_transport. enable_tls_wrapping ( ) ;
571572 log:: info!( "Full TLS session emulation enabled for protocol: {}" , protocol_id. as_str( ) ) ;
572573 }
@@ -645,16 +646,71 @@ async fn handle_tunnel_connection(
645646 }
646647 } ;
647648
648- // Create protocol wrapper matching client protocol
649- let wrapper = nooshdaroo:: ProtocolWrapper :: new ( protocol_id. clone ( ) , None ) ;
650- log:: debug!( "Created {} protocol wrapper for traffic obfuscation" , protocol_id. as_str( ) ) ;
651-
652649 // Relay data bidirectionally between client tunnel and target
653650 log:: debug!( "Starting bidirectional relay for {}:{}" , target_host, target_port) ;
654- if let Err ( e) = relay_tunnel_to_target ( tunnel_stream, noise_transport, target_stream, wrapper) . await {
655- log:: debug!( "Relay ended for {}:{}: {}" , target_host, target_port, e) ;
651+ if use_tls_emulation {
652+ // Use NoiseTransport's built-in TLS wrapping (no protocol wrapper)
653+ log:: debug!( "Using TLS session emulation (no protocol wrapper)" ) ;
654+ if let Err ( e) = relay_with_noise_only ( tunnel_stream, noise_transport, target_stream) . await {
655+ log:: debug!( "Relay ended for {}:{}: {}" , target_host, target_port, e) ;
656+ } else {
657+ log:: debug!( "Relay completed for {}:{}" , target_host, target_port) ;
658+ }
656659 } else {
657- log:: debug!( "Relay completed for {}:{}" , target_host, target_port) ;
660+ // Use protocol wrapper for obfuscation
661+ let wrapper = nooshdaroo:: ProtocolWrapper :: new ( protocol_id. clone ( ) , None ) ;
662+ log:: debug!( "Created {} protocol wrapper for traffic obfuscation" , protocol_id. as_str( ) ) ;
663+ if let Err ( e) = relay_tunnel_to_target ( tunnel_stream, noise_transport, target_stream, wrapper) . await {
664+ log:: debug!( "Relay ended for {}:{}: {}" , target_host, target_port, e) ;
665+ } else {
666+ log:: debug!( "Relay completed for {}:{}" , target_host, target_port) ;
667+ }
668+ }
669+
670+ Ok ( ( ) )
671+ }
672+
673+ /// Relay using NoiseTransport only (for TLS session emulation)
674+ async fn relay_with_noise_only (
675+ mut tunnel : tokio:: net:: TcpStream ,
676+ mut noise : NoiseTransport ,
677+ mut target : tokio:: net:: TcpStream ,
678+ ) -> Result < ( ) > {
679+ use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
680+
681+ let mut target_buf = vec ! [ 0u8 ; 8192 ] ;
682+
683+ loop {
684+ tokio:: select! {
685+ // Read from tunnel (TLS-wrapped), unwrap+decrypt, write to target
686+ result = noise. read( & mut tunnel) => {
687+ match result {
688+ Ok ( data) if !data. is_empty( ) => {
689+ // NoiseTransport.read() handles TLS unwrapping AND decryption
690+ target. write_all( & data) . await ?;
691+ }
692+ Ok ( _) => break , // Empty read = EOF
693+ Err ( e) => {
694+ log:: debug!( "Noise read error: {}" , e) ;
695+ break ;
696+ }
697+ }
698+ }
699+ // Read from target, encrypt+wrap with TLS, write to tunnel
700+ result = target. read( & mut target_buf) => {
701+ match result {
702+ Ok ( 0 ) => break , // EOF
703+ Ok ( n) => {
704+ // NoiseTransport.write() handles encryption AND TLS wrapping
705+ noise. write( & mut tunnel, & target_buf[ ..n] ) . await ?;
706+ }
707+ Err ( e) => {
708+ log:: debug!( "Target read error: {}" , e) ;
709+ break ;
710+ }
711+ }
712+ }
713+ }
658714 }
659715
660716 Ok ( ( ) )
0 commit comments