Skip to content

client::Handle::channel_open_direct_tcpip blocks and does not return until connection fails. #329

@dcechano

Description

@dcechano

I am trying to set up simple port forwarding through a jump host. I am doing this by using client::connect to get a client::Handle then (after authenticating) using the handle to open a Tcp/Ip forwarding channel through client::Handle::channel_open_direct_tcpip.

      let socketaddr: Vec<SocketAddr> =
            tokio::net::lookup_host(format!("{}:{}", SETTINGS.jump_host, SETTINGS.ssh_port))
                .await?
                .collect();

        let config = Arc::new(config);
        let sh = Client;

        let mut handle = client::connect(config, socketaddr.as_slice(), sh)
            .await
            .expect("Client connection failed");

        let auth_res = handle
            .authenticate_publickey(SETTINGS.username, Arc::new(key_pair))
            .await
            .expect("public key authentication failed");

        if !auth_res {
            anyhow::bail!("Authentication failed");
        }
        
        // This call blocks
        let channel = handle
            .channel_open_direct_tcpip(
                SETTINGS.remote_host,
                SETTINGS.remote_port,
                "localhost",
                SETTINGS.local_port,
            )
            .await
            .expect("Error while port forwarding.");

        // This line never gets to execute.
        println!("Forwarding channel (ostensibly) connected!");

        // let mut reader = channel.make_reader();
        // let mut writer = channel.make_writer();

        Ok(Self {
            handle,
            id: channel.id(),
        })

I have noticed that the Handler::openssh_ext_host_keys_announced is the last Handler method to execute. This suggests that the server is responding to the forwarding request and willing to allow it. I am suspicious that I am not implementing this method properly and the server is waiting for me to confirm the public keys and it eventually stops waiting and closes the connection. Is this correct? If so how do you confirm the public keys?

#[async_trait]
impl Handler for Client {
    type Error = russh::Error;

    /// Other methods are not shown.
    /// I have them written so they panic,
    /// so I know they are not being called.
    #[allow(unused_variables)]
    async fn check_server_key(
        &mut self,
        _server_public_key: &PublicKey,
    ) -> Result<bool, Self::Error> {
        //TODO impl proper public key checking
        Ok(true)
    }

    /// Called when the server signals success.
    #[allow(unused_variables)]
    async fn openssh_ext_host_keys_announced(
        &mut self,
        keys: Vec<PublicKey>,
        session: &mut Session,
    ) -> Result<(), Self::Error> {
        println!("openssh_ext_host_keys_announced");
        Ok(())
    }
}

To investigate I have confirmed that the server is responding to ssh and port forwarding by using the GNU ssh command that is native to linux. I have also opened connections without port forwarding (via russh) and they seem to return just fine. Does any one have any suggestions on avenues I could explore that may shed light on the issue? I appreciate the help. Thank you! (Console output below)

Opening forwarding channel.
openssh_ext_host_keys_announced
thread 'tokio-runtime-worker' panicked at /home/.../repos/p3-command-center2/src-tauri/src/session.rs:63:14:
Error while port forwarding.: ChannelOpenFailure(ConnectFailed)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at src-tauri/src/main.rs:110:6:
called `Result::unwrap()` on an `Err` value: JoinError::Panic(Id(9), ...)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions