A solution is to use ssh -ttt
on compute_mine:
ssh -ttt compute_remote_1 'exec ssh -NL 8080:localhost:80 compute_remote_2'
(-t
is usually enough, but -tt
will do what we want even if there is no local terminal.)
This will allocate a tty on compute_remote_1 and start a shell as the controlling process of the tty. The shell will execute exec ssh …
an thus replace itself with ssh
. The point is we want ssh
to be the controlling process. Some shells exec
the last command automatically (an optimization, a sane behavior when there is nothing more to do), but it's better to exec
explicitly in case the shell on compute_remote_1 is not that smart.
The easiest way to terminate the port forwarding by acting on compute_mine is to type Ctrl+c it the terminal where our ssh -t
runs (if such terminal exists). This won't directly kill ssh -t
, ^C
will get to compute_remote_1 and the tty there will kill ssh -NL
(see this answer). Our local ssh -t
will exit later.
ssh
on compute_mine may exit first for whatever reason, e.g. you may kill
it. If this happens and if sshd
on compute_remote_1 notices (depending on circumstances it may or may not notice immediately, see this answer), then the tty on compute_remote_1 will be closed and the controlling process will get SIGHUP. We made sure the controlling process is ssh
that handles the port forwarding, SIGHUP will terminate it. This way the port forwarding is automatically terminated when the ssh
process on compute_mine terminates.