Skip to content

Instantly share code, notes, and snippets.

@Eugeny
Created September 27, 2024 20:11
Show Gist options
  • Save Eugeny/9eb1c607ffa64b17453c8006e252ae45 to your computer and use it in GitHub Desktop.
Save Eugeny/9eb1c607ffa64b17453c8006e252ae45 to your computer and use it in GitHub Desktop.
use std::net::SocketAddr;
use std::sync::Arc;
use russh::client;
use tokio::net::TcpListener;
struct Client {}
#[async_trait::async_trait]
impl client::Handler for Client {
type Error = russh::Error;
async fn check_server_key(
&mut self,
_server_public_key: &russh_keys::key::PublicKey,
) -> Result<bool, Self::Error> {
Ok(true)
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
env_logger::init();
let listener = TcpListener::bind("0.0.0.0:50000").await?;
log::info!("Listening on port 50000");
loop {
// Accept incoming connections
let (mut socket, addr) = listener.accept().await?;
log::info!("Accepted connection from {:?}", addr);
let jump_host = "192.168.78.233";
let target_host = "192.168.77.254";
let jump_host_user = "root";
let jump_host_pwd = std::env::args().collect::<Vec<_>>()[1].clone();
// Spawn a new task to handle the connection
tokio::spawn(async move {
// Configure the SSH client
let mut config = client::Config::default();
config.inactivity_timeout = Some(std::time::Duration::from_secs(3600 * 60));
let config = Arc::new(config);
// Connect to the SSH server
let addr: Vec<SocketAddr> = tokio::net::lookup_host(format!("{}:{}", jump_host, 22))
.await?
.collect();
let mut jump_handle =
client::connect(config.clone(), addr.as_slice(), Client {}).await?;
// Authenticate
let is_authenticated = jump_handle
.authenticate_password(jump_host_user, jump_host_pwd)
.await?;
if !is_authenticated {
anyhow::bail!("failed to authenticate");
} else {
log::info!("authenticated");
}
let (mut reader, mut writer) = socket.split();
let mut channel = jump_handle
.channel_open_direct_tcpip(target_host, 22, "localhost", 12345)
.await?;
let mut ch_writer = channel.make_writer();
let mut ch_reader = channel.make_reader();
let read_fut = async move {
let _ = tokio::io::copy(&mut reader, &mut ch_writer).await;
log::info!("Channel writer loop ended, channel will send EOF");
};
let write_fut = async move {
let _ = tokio::io::copy(&mut ch_reader, &mut writer).await;
log::info!("Channel reader loop ended, channel received EOF");
};
let _ = tokio::join!(read_fut, write_fut);
log::info!("Both copy loops ended");
Ok(())
});
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment