Programmatically open a SSH tunnel in active session?

I'm aware that after starting a new SSH session I can open the SSH shell to start a new tunnel (Enter then ~ and finally C):

>ssh -L 9000:localhost:9000
Forwarding port.

Is there a way to do it in a non-interactive way, while already SSHd in?

I'm ignoring security implications here, this is for local development situation where I might need to open a tunnel to a server which will be listening on a random port.


Solution 1:

You can do it, with some preparation beforehand: setting the (first) ssh command as a master ssh, using -M/ControlMaster and -S/ControlPath. Normally the ControlMaster feature is intended to run multiple ssh shells to the same destination over a single ssh authentication using its single TCP connection. But you can also run an other ssh command with the -O ctl_cmd to add the additional forwarding instead:

-O ctl_cmd

Control an active connection multiplexing master process. When the -O option is specified, the ctl_cmd argument is interpreted and passed to the master process. Valid commands are: “check” (check that the master process is running), “forward” (request forwardings without command execution), “cancel” (cancel forwardings), “exit” (request the master to exit), and “stop” (request the master to stop accepting further multiplexing requests).

terminal1:

ssh -S /tmp/exampleinsecuresocket -M remoteuser@remotehost

terminal2:

ssh -S /tmp/exampleinsecuresocket -O forward -L 9000:localhost:9000 remoteuser@remotehost

Note that terminal2's ssh will immediately exit and not ask for authentication even if it should normally have been expected: it didn't do any connection to remotehost but just told the ssh already running in terminal1 to do the LocalForward. The ssh running in terminal1 now has an additional port forwarded. Of course this is non-interactive and can be done in a script.

With adequate use of parameters like -o ControlMaster auto and a correct scheme with adequate tokens for the ControlPath option as described in the manual, one can automate the initial settings in ~/.ssh/config for any destination.