Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help when implementing a simple local port forwarding #256

Open
charlesxsh opened this issue Feb 27, 2024 · 1 comment
Open

Help when implementing a simple local port forwarding #256

charlesxsh opened this issue Feb 27, 2024 · 1 comment

Comments

@charlesxsh
Copy link

let listener = TcpListener::bind("0.0.0.0:60000").await?;
    println!("Listening on port 60000");

    loop {
        // Accept incoming connections
        let (mut socket, addr) = listener.accept().await?;

        println!("Accepted connection from {:?}", addr);
        let jump_host = jump_host.clone();
        let target_host = target_host.clone();
        let jump_host_user = jump_host_user.cloned();
        let jump_host_pwd = jump_host_pwd.cloned();
        // 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);
            let sh = Client {};
            // Connect to the SSH server
            let addr: Vec<SocketAddr> =
                tokio::net::lookup_host(format!("{}:{}", jump_host, jump_host_port))
                    .await?
                    .collect();
            let mut jump_handle = client::connect(config.clone(), addr.as_slice(), sh).await?;

            if jump_host_user.is_some() && jump_host_pwd.is_some() {
                // Authenticate
                let is_authenticated = jump_handle
                    .authenticate_password(jump_host_user.unwrap(), jump_host_pwd.unwrap())
                    .await?;

                if !is_authenticated {
                    bail!("failed to authenticate");
                } else {
                    info!("authenticated");
                }
            } else {
                bail!("TODO: authentication other than password");
            }
            let mut buffer = [0; 1024];
            let (mut reader, mut writer) = socket.split();
            let mut channel = jump_handle
                .channel_open_direct_tcpip(target_host, target_host_port, "localhost", local_port)
                .await?
                .into_stream();

            loop {
                tokio::select! {
                    _ = tokio::io::copy(&mut reader, &mut channel) => {},
                    _ = tokio::io::copy(&mut channel, &mut writer) => {},        ///cannot borrow `channel` as mutable more than once at a time
                };
        });
        
    }
}

I am trying to write a simple program that listens on local port 60000 and forwards ssh traffic to target_host through jump_host.
At a high level, I knew I needed to listen to local socket traffic and handle read/write from connection to jump_host.
However, I feel like I completely misunderstood how to implement local port forwarding by using this library since this library API design does allow me to do it this way.
Does anyone can enlighten me on how to achieve this goal? (maybe I need to set up russh server to listen port and then forward traffic? )

@Eugeny
Copy link
Member

Eugeny commented Feb 27, 2024

You're on the right track. Just use Channel::make_reader and Channel::make_writer instead of into_stream to split it into independent halves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants