17

How can I rewrite the following command with ProxyCommand?

ssh -l username1 -t jumphost1 \
ssh -l username2 -t jumphost2 \
ssh -l username3 -t jumphost3 \
ssh -l username4    server

This doesn't work

ssh -o ProxyCommand="\
ssh -l username1 -t jumphost1  \
ssh -l username2 -t jumphost2  \
ssh -l username3 -t jumphost3" \
    -l username4    server

username1@jumphost1's password:
Pseudo-terminal will not be allocated because stdin is not a terminal.
Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
ssh_exchange_identification: Connection closed by remote host

I'm aware of its use with nc, but I'm searching for way to use it with 3+ hops, and also use this option with scp. I checked ssh_config man page, but the information is quite scarce, for me at least.

EDIT

I tried using ProxyCommand nested in another ProxyCommand as suggested below but I always get something along the following lines

debug3: ssh_init_stdio_forwarding: 192.17.2.2:2222
debug1: channel_connect_stdio_fwd 192.17.2.2:2222
debug1: channel 0: new [stdio-forward]
debug2: fd 4 setting O_NONBLOCK
debug2: fd 5 setting O_NONBLOCK
debug1: getpeername failed: Bad file descriptor
debug3: send packet: type 90
debug2: fd 3 setting TCP_NODELAY
debug3: ssh_packet_set_tos: set IP_TOS 0x10
debug1: Requesting no-more-sessions@openssh.com
debug3: send packet: type 80
debug1: Entering interactive session.

Fortunately, since 7.3 -J or ProxyJump serves my purpose — although I still to have to work around my keys setup.

ssh -q -J user1@jumphost1,user2@jumphost2,user3@jumphost3 user@server
25

The nc version is not recommended anymore. Use the -W switch, which is provided in recent versions of OpenSSH. Also, you don't need to copy the config to other hosts! All of the config needs to be done on your host and it does not interfere with the scp in any way. Just create a file ~/.ssh/config with:

Host jumphost1
  User username1
Host jumphost2
  User username2
  ProxyCommand ssh -W %h:%p jumphost1
Host jumphost3
  User username3
  ProxyCommand ssh -W %h:%p jumphost2
Host server
  User username4
  ProxyCommand ssh -W %h:%p jumphost3

And then connect using ssh server or use scp file server:path/. If you insist on oneliner (or not sure what you mean about ProxyCommand nesting), then as already pointed out, it is hell of escapes:

ssh -oProxyCommand= \
  'ssh -W %h:%p -oProxyCommand= \
    \'ssh -W %h:%p -oProxyCommand= \
      \\\'ssh -W %h:%p username1@jumphost1\\\' \
    username2@jumphost2\' \
  username3@jumphost3' \
username4@server

You basically need to go from inside.

  • Thanks. Tried the one-liner, didn't work. I don't know if it's only the escaping. Can you double-check, please? Also, can you explain why nesting is necessary and chaining doesn't work? – 1.61803 Oct 21 '16 at 16:41
  • 1
    Well, What does "does not work!" mean? Chaining works, but not with scp, because SCP is expecting SCP control messages, but instead gets SSH control messages and fails. On the other hand, the ProxyCommand does it transparently and therefore the outermost ssh (or scp) will get the messages directly from the other end. – Jakuje Oct 21 '16 at 17:33
  • I get the > prompt where is waiting to break the line continuation, I guess — ie, the command never executes. – 1.61803 Oct 22 '16 at 14:31
  • 1
    @TrevorBoydSmith Because it requires you to have some external program (nc) installed on all the proxy hosts. The IO redirect using -W does not need that and only requirement is to have openssh client installed on your computer. – Jakuje Jul 4 at 13:34
  • 2
    @RomanDodin double % should work: %%h in your case – Jakuje Nov 20 at 11:54
-1

I have done this with two hops, but it should work for three. The simplest way is to have the ~/.ssh/config file set on each host. So, if you want to be on hosta and get to hostd via hostb and hostc`, you could set your configurations thusly:

In hosta:~/.ssh/config:

Host hostd
    User username
    ProxyCommand ssh hostb nc %h %p 2> /dev/null

In hostb:~/.ssh/config:

Host hostd
    User username
    ProxyCommand ssh hostc nc %h %p 2> /dev/null

In hostc:~/.ssh/config:

Host hostd
    User username
    ProxyCommand ssh hostd nc %h %p 2> /dev/null

You can then ssh hostd on any of the hosts in the chain and you'll make your way to hostd.

Using netcat for the proxy does not interfere with scp.

If for some reason you really don't want to use local ~/.ssh/config files, you can do this on hosta:

ssh -oProxyCommand='ssh -oProxyCommand=\'ssh -o ProxyCommand=\\\'ssh username@hostd nc %h %p 2>/dev/null\\\' username@hostc nc %h %p 2> /dev/null' username@hostb nc %h %p 2> /dev/null' username@hostd
  • As I said, I'm aware of nc's use. Can you actually rewrite the command I posted with ProxyCommand as an option? – 1.61803 Oct 19 '16 at 17:33
  • You mention "you're aware of its use but want to use scp". It doesn't interfere with scp. But I will give you the comically long command as an edit shortly. – DopeGhoti Oct 19 '16 at 17:40
  • Thanks. Could you just rewrite your answer focusing on ProxyCommand nesting? If you reread my post you'll see that's the gist. I thought I could, instead of nesting like you did, chain all the middle nodes in ProxyCommand. I still wonder if that's somehow possible. – 1.61803 Oct 19 '16 at 20:13
  • That is in fact what is being done; it's just a lot harder to read than in situ configurations because of all the nested (and increasingly escaped) quotes. You have to do it that way because you are carrying all of the ProxyCommand directives along with you to the next host in the chain. – DopeGhoti Oct 19 '16 at 21:28
  • This is wrong. The configuration is only on your local computer, not distributed among the hosts on the way as you try to propose. – Jakuje Jan 26 '18 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.