please i need help using Thrussh or Russh ssh create
i am trying to implement a small program that ssh into a server using another server as a jump host.
I was successfully able to ssh directly, request pty and shell etc directly but when trying to implement jump host i get disconnect error when trying to connect to the target using the jumphost stream
mod actor;
use russh::client as client_lib;
use std::sync::Arc;
use async_trait::async_trait;
use russh::{client, ChannelId};
use russh_keys::key::PublicKey;
#[actix_rt::main]
async fn main() {
let config = client_lib::Config::default();
let jumphost = "172.17.181.25";
let jumphost_port = 22;
let jumphost_username = "username";
let jumphost_password = "password";
let client = SshClient {
host: "172.17.181.27",
port: 22,
username: "username",
password: "password",
};
let custom_config = Arc::new(config);
let mut jumphost_session = client_lib::connect(
custom_config.clone(),
(jumphost, jumphost_port),
client.clone(),
)
.await
.unwrap();
if jumphost_session
.authenticate_password(jumphost_username, jumphost_password)
.await
.unwrap()
{
let channel_stream = jumphost_session
.channel_open_direct_tcpip(client.host, client.port as u32, "127.0.0.1", 0)
.await
.unwrap()
.into_stream();
let mut ts =
client_lib::connect_stream(custom_config.clone(), channel_stream, client.clone())
.await;
let mut target_session = ts.unwrap(); // <= Disconnect Error occurred hear
let is_authenticated = target_session
.authenticate_password(client.username, client.password)
.await
.unwrap();
if is_authenticated {
let mut channel = target_session.channel_open_session().await.unwrap();
channel
.request_pty(true, "xterm", 200, 200, 200, 200, &[])
.await
.unwrap();
channel.request_shell(true).await.unwrap();
channel.data(&b"ls -ls\n"[..]).await.unwrap();
}
// loop {
// if let Some(msg) = channel.wait().await {
// match msg {
// ChannelMsg::Eof => {
// println!("Server closed connection");
// std::process::exit(0);
// }
// ChannelMsg::Success => println!("Something was successfull"),
// ChannelMsg::Data { data } => println!("{:?}", data),
// ChannelMsg::Open {
// id,
// max_packet_size,
// window_size,
// } => {
// println!("ID: {id}, PACKET_SIZE: {max_packet_size}, WINDOW_SIZE: {window_size}")
// }
// ChannelMsg::Exec {
// want_reply,
// command,
// } => println!("{:?}:::{:?}", want_reply, command),
// ChannelMsg::ExtendedData { data, ext } => println!("{:?} {:?}", data, ext),
// ChannelMsg::Failure => println!("Failure"),
// ChannelMsg::ExitStatus { exit_status } => println!("{:?}", exit_status),
// ChannelMsg::Close => println!("close returned"),
//
// _ => println!("Something Else"),
// }
// dbg!(msg);
// }
// }
}
}
#[derive(Debug, Clone)]
pub struct SshClient<'client> {
pub host: &'client str,
pub port: u16,
pub username: &'client str,
pub password: &'client str,
}
#[async_trait]
impl<'client> client::Handler for SshClient<'client> {
type Error = anyhow::Error;
async fn check_server_key(
self,
server_public_key: &PublicKey,
) -> Result<(Self, bool), Self::Error> {
println!("check server public key {:?}", server_public_key);
Ok((self, true))
}
async fn data(
self,
channel: ChannelId,
data: &[u8],
session: client::Session,
) -> Result<(Self, client::Session), Self::Error> {
println!(
"data on channel {:?}: {:?}",
channel,
String::from_utf8_lossy(data)
);
Ok((self, session))
}
}
here is the complete outoput
/home/blackdante/Development/learning/rust/learn_ssh/target/debug/learn_ssh
check server public key Ed25519(PublicKey(CompressedEdwardsY: [35, 56, 108, 175, 224, 8, 99, 157, 102, 61, 119, 255, 169, 228, 68, 113, 138, 84, 167, 146, 179, 137, 106, 184, 142, 22, 151, 15, 178, 211, 54, 25]), EdwardsPoint{
X: FieldElement51([1630537806071078, 648316631189368, 793242739809564, 1818755964497301, 2232763494220464]),
Y: FieldElement51([854186038933539, 1477670205182892, 735926167081874, 922886286399945, 443572329445745]),
Z: FieldElement51([1, 0, 0, 0, 0]),
T: FieldElement51([1505040704566283, 1894851419557823, 1376022236302954, 2064758804968182, 1505568779901593])
}))
data on channel ChannelId(2): "SSH-2.0-OpenSSH_8.0\r\n"
data on channel ChannelId(2): "\0\0\u{4}\u{14}\u{5}\u{14}V(#\u{e}\u{1a}k\u{2}\u{4}\u{1a}��倿��\0\0\u{1}%curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nist521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1\0\0\0Arsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519\0\0\0waes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc\0\0\0waes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc\0\0\0�hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha1,umac-128@openssh.com,hmac-sha2-512\0\0\0�hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha1,umac-128@openssh.com,hmac-sha2-512\0\0\0\u{15}none,zlib@openssh.com\0\0\0\u{15}none,zlib@openssh.com\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Disconnected', src/main.rs:52:37
stack backtrace:
0: rust_begin_unwind
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/std/src/panicking.rs:593:5
1: core::panicking::panic_fmt
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/panicking.rs:67:14
2: core::result::unwrap_failed
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/result.rs:1651:5
3: core::result::Result<T,E>::unwrap
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/result.rs:1076:23
4: learn_ssh::main::{{closure}}
at ./src/main.rs:52:34
5: <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/local.rs:923:42
6: tokio::task::local::LocalSet::with::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/local.rs:684:13
7: std::thread::local::LocalKey<T>::try_with
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/std/src/thread/local.rs:270:16
8: std::thread::local::LocalKey<T>::with
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/std/src/thread/local.rs:246:9
9: tokio::task::local::LocalSet::with
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/local.rs:667:9
10: <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/local.rs:913:9
11: tokio::task::local::LocalSet::run_until::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/local.rs:573:19
12: <core::pin::Pin<P> as core::future::future::Future>::poll
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/future/future.rs:125:9
13: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:541:57
14: tokio::runtime::coop::with_budget
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/coop.rs:107:5
15: tokio::runtime::coop::budget
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/coop.rs:73:5
16: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:541:25
17: tokio::runtime::scheduler::current_thread::Context::enter
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:350:19
18: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:540:36
19: tokio::runtime::scheduler::current_thread::CoreGuard::enter::{{closure}}
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:615:57
20: tokio::macros::scoped_tls::ScopedKey<T>::set
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/macros/scoped_tls.rs:61:9
21: tokio::runtime::scheduler::current_thread::CoreGuard::enter
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:615:27
22: tokio::runtime::scheduler::current_thread::CoreGuard::block_on
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:530:19
23: tokio::runtime::scheduler::current_thread::CurrentThread::block_on
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/scheduler/current_thread.rs:154:24
24: tokio::runtime::runtime::Runtime::block_on
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/runtime/runtime.rs:302:47
25: tokio::task::local::LocalSet::block_on
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/local.rs:534:9
26: actix_rt::runtime::Runtime::block_on
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/actix-rt-2.8.0/src/runtime.rs:82:9
27: actix_rt::system::SystemRunner::block_on
at /home/blackdante/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/actix-rt-2.8.0/src/system.rs:210:9
28: learn_ssh::main
at ./src/main.rs:12:1
29: core::ops::function::FnOnce::call_once
at /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.