Ssh – How does ssh ProxyCommand actually work

PROXYsshssh-tunnel

I am comfortable with using the ProxyCommand feature of ssh and can use it to hop through mulitple bastion hosts to reach the final host efficiently. But I just can't seem to understand how it actually works in the backend.

For eg. I have the following config file.

Host final
Hostname final.com
Port 22
AgentForwarding yes
User guestuser
ProxyCommand "ssh user@bastion.com -W %h:%p"

I understand that for connecting to host final, the ProxyCommand will run prior to making the connection to final.com. But I still can't seem to understand the order of connections.

And what does the option -W %h:%p do? I understand that it is the netcat feature and is similar to nc %h %p.

So as far as my understanding goes here is the sequence of operations. Kindly let me know if I am wrong. I'm will be using the config file specified above in my example.

  1. The user enters ssh final
  2. An ssh connection to bastion.com
    created.
  3. A netcat tunnel is created from bastion.com to port 22
    of final.com. The stdin of netcat is connected to the shell obtained
    in the connection to bastion.com.
  4. So now we have a connection
    from our system to final.com. The first half of this connection is
    an ssh connection from our system to bastion.com. The second half of
    this connection is a netcat tunnel from bastion.com to final.com.
  5. Now ssh final command takes the above connection as a proxy and
    tunnels its data through this existing connection.

Additionally I would also like to know whether this techniques is also known as ssh stacking?

added linebreaks

Best Answer

3) A netcat tunnel is created from bastion.com to port 22 of final.com.

false, there's no netcat.

1) The user enters ssh final on localhost. This launches the parent ssh process
2) The parent ssh creates a child ssh with I/O redirected to pipes
3) The child ssh creates a connection to bastion.com.
4) The sshd process on bastion.com creates a tcp connection to final.com:22
5) An ssh channel is added to existing ssh connection between localhost and bastion.com
6) Parent ssh writes the handshake data to the pipe, the child ssh reads it from the pipe, sends via the ssh channel to sshd on bastion.com; sshd reads it and writes it to the socket connected to final.com. Similarly, the data is transmitted from final.com to localhost