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.


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:
debug1: channel_connect_stdio_fwd
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 [email protected]
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

2 Answers 2


use a simple ssh config file

The nc version is not recommended with newer versions of ssh. Instead use the -W switch from more 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.

Here is an example ~/.ssh/config file for your given example:

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

finally: connect using ssh server or scp file server:path/ or rsync.


For those of you who prefer a drawing instead of text in a ssh config file, here is a signal flow diagram:


p.p.s. for fun here is a oneline but please note this approach is hard to type and hard to read:

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

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
    Commented Oct 21, 2016 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
    Commented Oct 21, 2016 at 17:33
  • 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
    Commented Jul 4, 2019 at 13:34
  • 3
    @RomanDodin double % should work: %%h in your case
    – Jakuje
    Commented Nov 20, 2019 at 11:54
  • 4
    Thanks @Jakuje for the sake of completeness, I provide the full command here for the src->jmp1->jmp2->dev path, where the command is issued on src and the target machine is dev ssh -o "ProxyCommand=ssh -W %h:%p -o 'ProxyCommand=ssh -W %%h:%%p root@jmp1' root@jmp2" admin@dev Commented Nov 21, 2019 at 12:10

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
    Commented Oct 19, 2016 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
    Commented Oct 19, 2016 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
    Commented Oct 19, 2016 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
    Commented Oct 19, 2016 at 21:28
  • 1
    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
    Commented Jan 26, 2018 at 14:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .