Does OpenSSH support multihop login?

Solution 1:

I do not know how Ansible uses OpenSSH.


But OpenSSH itself supports "multihop logins".

Since OpenSSH 7.3, you can use -J (jump) switch like:

ssh -J [email protected] [email protected]

The -J is an equivalent of ProxyJump directive:

ssh -o [email protected] [email protected]

Note that with file transfer tools, like scp and sftp, the -J switch is supported since 8.0 only. With older versions (but at least 7.3), use ProxyJump. See How can I download a file from a host I can only SSH to through another host?

Also note that the versions refer to local versions of OpenSSH. A remote version of OpenSSH is not relevant.


As @GordonDavisson commented, with older versions (but at least 5.4), you can use ProxyCommand directive and -W switch:

ssh -o ProxyCommand="ssh -W %h:%p [email protected]" [email protected]

With even older versions, you can use nc command instead of the -W:

ssh -o ProxyCommand="ssh user2@%h nc host2.example.com 22" \
    -o HostKeyAlias=host2.example.com \
    host1.example.com

All the above options are covered in more details in Wikibooks article OpenSSH/Cookbook/Proxies and Jump Hosts.


Another options is to use port forwarding (-L switch). But that involves two ssh instances. I'm not sure if that's possible with Ansible.

Solution 2:

For older Ansible versions you had to do it in the general SSH config as described in Martin Prikryls answer. New versions have Ansible specific config as described in the general FAQ

How do I configure a jump host to access servers that I have no direct access to?

You can set a ProxyCommand in the ansible_ssh_common_args inventory variable. Any arguments specified in this variable are added to the sftp/scp/ssh command line when connecting to the relevant host(s). Consider the following inventory group:

[gatewayed] foo ansible_host=192.0.2.1 bar ansible_host=192.0.2.2

You can create group_vars/gatewayed.yml with the following contents:

ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q [email protected]"'

Ansible will append these arguments to the command line when trying to connect to any hosts in the group gatewayed. (These arguments are used in addition to any ssh_args from ansible.cfg, so you do not need to repeat global ControlPersist settings in ansible_ssh_common_args.)

Note that ssh -W is available only with OpenSSH 5.4 or later. With older versions, it’s necessary to execute nc %h:%p or some equivalent command on the bastion host.

With earlier versions of Ansible, it was necessary to configure a suitable ProxyCommand for one or more hosts in ~/.ssh/config, or globally by setting ssh_args in ansible.cfg.

This way you have a very Ansible-esque way of setting up SSH bastion hosts only where needed, together with any other special SSH settings (like keys, users, etc).