Skip to content

Commit 178bc65

Browse files
0xinf0claude
andcommitted
Add server-side TLS session emulation relay support
Server was still using protocol wrapper relay even when TLS session emulation was enabled, causing the same double-wrapping issue. Added relay_with_noise_only() function to server code (main.rs) that uses NoiseTransport read/write directly for TLS emulation mode. Now both client and server properly handle TLS session emulation without protocol wrapper conflicts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 44bd098 commit 178bc65

File tree

1 file changed

+64
-8
lines changed

1 file changed

+64
-8
lines changed

src/main.rs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)