ssh jump host

315 views
Skip to first unread message

Sergey Skripnick

unread,
Mar 21, 2016, 12:20:31 PM3/21/16
to asyncssh-users
Hi all.

Currently we can directly connect from ssh server to any host/port:

 chan
, session = yield from conn.create_connection(MySSHTCPSession,'www.google.com', 80)

It would be useful to be able to create ssh connections as well:

 new_conn, new_client = yield from conn.create_ssh_connection(MySSHClient, "192.168.122.22")

Or it is already possible?

Ron Frederick

unread,
Mar 21, 2016, 11:12:22 PM3/21/16
to Sergey Skripnick, asyncssh-users
Hi Sergey,

It’s possible today to open an upstream SSH connection over an existing SSH tunnel, though it’s not quite as direct as you asked for here. The simplest way is to propose set up port forwarding. For instance:

    with (yield from asyncssh.connect(‘host1')) as conn:
        listener = yield from conn.forward_local_port('localhost', 8022, ‘host2', 22)

        with (yield from asyncssh.connect('localhost', 8022)) as conn2:
            ...Open sessions on conn2...

The only minor bit of trickiness is that you’d need to add an entry in your known_hosts file for [localhost]:8022 which lists whatever server host keys you’re expecting to get back from host2.

I like your idea to provide a direct call that simplifies this, though. It would make it possible to use the known_hosts entry for host2 that’s already there, even though the connection is being tunneled. It would also mean that a one-time direct connection could be used, rather than having to set up port forwarding. I’ll look into adding this - thanks for the suggestion!
-- 
Ron Frederick



Sergey Skripnick

unread,
Mar 22, 2016, 12:28:20 PM3/22/16
to asyncssh-users, sskri...@mirantis.com
Hi Ron.

Thank you for reply.

I also remembered about python's ssl.wrap_socket, and probably it would be more flexible to have something like this

Ron Frederick

unread,
Mar 23, 2016, 1:31:02 AM3/23/16
to Sergey Skripnick, asyncssh-users
Hi Sergey,

When I first wrote AsyncSSH, I thought about providing a “sock” argument on create_connection(), similar to the underlying asyncio.create_connection(). However, this didn’t really make sense since I needed the host & port information to be passed in to do proper known_hosts checking. We’ve got a similar issue here, where it wouldn’t make sense to pass in an SSHChannel or SSHSession that’s already connected to the target host & port if those arguments still need to be provided to know which known_hosts entry to use.

Instead, I’m thinking it might make sense to offer a “tunnel” argument on create_connection() where you pass in an open SSHConnection object. Doing this would cause it to call create_connection() on that existing SSH connection to open a direct TCP connection to the requested host and port and then start running SSH over that.

I also kind of liked your original suggestion of a “create_ssh_connection” method on SSHConnection, and may offer that and “connect_ssh” as new SSHConnection methods that would call the top level create_connection() or connect() with this new “tunnel” argument.

Sergey Skripnick

unread,
Mar 23, 2016, 8:45:10 AM3/23/16
to asyncssh-users, sskri...@mirantis.com
Hi Ron.

But you can get this information by getpeername() method.

Ron Frederick

unread,
Mar 23, 2016, 9:20:44 AM3/23/16
to Sergey Skripnick, asyncssh-users
This returns an IP address, not a hostname. While known_hosts can be based on IP, the entries may only be listed by hostname (or a partial hostname like just the domain name). So, we need to provide both hostname and IP address to the known_hosts lookup.

On Mar 23, 2016, at 5:45 AM, Sergey Skripnick <sskri...@mirantis.com> wrote:
But you can get this information by getpeername() method.


When I first wrote AsyncSSH, I thought about providing a “sock” argument on create_connection(), similar to the underlying asyncio.create_connection(). However, this didn’t really make sense since I needed the host & port information to be passed in to do proper known_hosts checking. We’ve got a similar issue here, where it wouldn’t make sense to pass in an SSHChannel or SSHSession that’s already connected to the target host & port if those arguments still need to be provided to know which known_hosts entry to use.
-- 
Ron Frederick



Ron Frederick

unread,
Mar 26, 2016, 1:44:04 AM3/26/16
to Sergey Skripnick, asyncssh-users
Hi Sergey,

I just checked in a first cut at tunneled SSH connection support in the “develop” branch. I haven’t added the “create_ssh_connection” methods on SSHConnection yet, but I did add a new “tunnel” argument to the top-level asyncssh.create_connection() and asyncssh.connect() functions. If you get a chance to check it out, let me know what you think! The current syntax looks something like:

    with (yield from asyncssh.connect(‘host1')) as conn:
        with (yield from asyncssh.connect(‘host2', tunnel=conn)) as conn2:
            ...Open sessions on conn2...

I’m thinking of also supporting:

    with (yield from asyncssh.connect(‘host1')) as conn:
        with (yield from conn.connect_ssh(‘host2')) as conn2:
            ...Open sessions on conn2...

There could also be a conn.create_ssh_connection() method, which would work like asyncssh.create_connection().

Sergey Skripnick

unread,
Mar 28, 2016, 12:33:55 PM3/28/16
to asyncssh-users, sskri...@mirantis.com

This is awesome. Works as expected. Thanks a lot!
 
Reply all
Reply to author
Forward
0 new messages