http://www.perlmonks.org?node_id=999412


in reply to Multilevel SSH

I know your pain. Server A, for me, might be a hardware monitor. Server B might be a management node. Server C might be the node I care about. In my case, if I need A at all, I set up an ssh tunnel there, and then I ssh "directly" to server B (on a special port on localhost if A was needed), and then from there I ssh to C. Server A always is connected to the corporate network, B might be, C might be as well, but much more rarely. (And sometimes my scripts run directly on server B, which adds some fun to the mix.)

Either one of these solutions may apply.

First, if A is needed, I look for the ssh tunnel process. If it doesn't exist, I create it. If another tunnel (to a different monitor) is already set up, I kill that before creating the new tunnel. (I'll eventually try to work out some smarts to use multiple ports here, but, until then, this is sufficient.) I set some env vars: PROXY_PORT to the port number, and SSH_HOSTNAME to the name I want to associate with this in the known_hosts file.

Then, I take the ssh command I want to run, and shell quote it (this is convoluted), and create the new ssh command around it:

@cmd = ('ssh', @ssh_options, # e.g., -o => 'ForwardX11 no' $user . '@' . $node, # e.g., root@serverC quote_cmd(@cmd) # this @cmd is the original command we want to + run. ); @cmd = ('ssh', @ssh_options, # e.g., -o => 'ForwardX11 no' $ENV{PROXY_PORT} ? (-p => $ENV{PROXY_PORT}) : (), $ENV{SSH_HOSTNAME} ? ? (-o => "HostKeyAlias $ENV{SSH_HOSTNAME} +") : (), $proxy, # localhost if A is needed, otherwise server B quote_cmd(@cmd) ) if $proxy;
In my case, I need my local ssh key to be valid on servers A (to create the proxy) and B (to log in there), and the ssh key on B to be valid on C.

So, the tricky bit is finding how to quote a command. That is probably best left to another node, and I'm sure it's been answered before here, as I'm sure I couldn't have figured out the edge cases on my own on the first try :-)