Just Enough Developed Infrastructure

Chaining SSH tunnels, Easy SSH hopping

When managing secure Unix infrastructure, you often find yourself hopping from one server to another by using SSH. Once I actually had a nightmare that I could not find the end of my SSH tunnel.... Hope this stops your nightmare:
Most commonly you would do:
client$  ssh user@server1 server1$ ssh user@server2 server2$ ....
When verifying services on the end server, you have to build up tunnels to be able to reach the ports. Typically people would build up a new ssh session and chain the tunnels (client -> server 1 and server -> server2), eventually creating a tunnel from your client machine to server2.
client$ ssh -L9999:localhost:9999 user@server1 server1$ ssh -L9999:localhost:9999 user@server2
Downsides:

  1. Only one port:The creation of tunnels in SSH is typically done by specifying one port (in fact it is mandatory). But this means that for each port you want to be tunneled you have to specify a new tunnel.
  2. Manual recreation: You have to login to server 1, then to server 2, ... This is just time consuming.
  3. Security: You could of course use keys instead of passwords but then you would have to put your keys on each intermediate server also
Netcat and Proxycommand to the rescue: Luckily there exist a more flexible way of doing this by using netcat and SSH ProxyCommand together.  The proxycommand allows you to specify a command you can use to reach the ssh host.
So in your .ssh/config you can specify
Host server2-entry         Protocol 2         Port 22         ProxyCommand ssh -C server1-entry nc <ip-of-server2-seen-from-server1> 22 Host server1-entry         Protocol 2         Port 22
When executing ssh server2-entry, it will first execute the server1-entry of your config asking for the password of server1 and then make a connection from server1 to server2. And if you use keys now, you can automate this. The difference is that the private key stays on client1 and does not need to be copied on server1! Making it more secure again.
Making a tunnel directly to server2 can be done : ssh -L9999:localhost:9999 server2-entry without first having to create the tunnel on server1.
More detail can be found at: http://fixunix.com/ssh/73544-how-do-i-setup-multiple-hop-tunnel-chain-port-forwarding.html Another solution: The downside is that for this trick to function , netcat needs to be copied on the intermediate hops. In our case server1. http://www.rschulz.eu/2008/09/ssh-proxycommand-without-netcat.html provides us with a possible solution on Linux (have not tested it). It revolves around intelligently using redirection to network pipe the in and outs of the tunnel.
ProxyCommand ssh {gw} 'exec 3<>/dev/tcp/{host}/22;(cat <&3 & );cat >&3'