opening a temporary tunnel

I have the following problem:

I have a remote machine accessible via ssh which can serve some data through a web interface.

I can use OpenSSH LocalForwarding to open a tunnel and start the remote server:

ssh user@my.remote.server -L 127.0.0.1:3333:localhost:4000 ./start.sh

then, on another terminal (or from GUI), I can start a browser, e.g.:

firefox localhost:3333/whatever

and access content served by my app.

After use I simply give [CTRL-C] to start.sh to close server, connection and tunnel.

So far so good.

Question is: Is it possible to write a script combining everything in such a way the tunnel is closed when browser terminates?

To be more precise I would like a script that:

  1. Opens the tunnel and starts remote server (as above).
  2. Automatically opens a browser (firefox is ok, but not a must) on the right port (which could be randomly generated).
  3. Keeps tunnel up while browser is running.
  4. When browser terminates (I am aware there could be other open windows, but that’s beyond the point) it should send a signal (SIGHUP) to server (start.sh).
  5. When remote server terminates tunnel should be closed (this should be automatic with the above setup)

I would like to keep tunnel and server up-and-running for the time strictly needed, avoiding to "forget closing" as it can happen if I have to do it manually.

How can I do this?

Asked By: ZioByte

||

It looks like you’ve already outlined most of the steps in your question. This is pretty much what you’re asking for:

#!/bin/sh

# start ssh in the background, and record the pid in $ssh_pid.
ssh -n -L 127.0.0.1:3333:localhost:4000 user@my.remote.server ./start.sh &
ssh_pid=$!

# start firefox. we're not running it in the background, so the
# script blocks here until firefox terminates.
firefox localhost:3333/whatever

# kill the ssh process
kill $ssh_pid

When remote server terminates tunnel should be closed (this should be automatic with the above setup)

If the remote ./start.sh command terminates, then ssh will exit. This script doesn’t take care of quitting firefox in that case, but the tunnel will no longer exist.

Answered By: larsks

It turns out answer is a bit more convoluted than expected.

I ended up writing a full init script for the server:

#!/bin/sh

# use start-stop-daemon to control zero-ui
set -e

# Must be a valid filename
NAME=zero-ui
PIDFILE=/home/user/$NAME.pid
DAEMON=/usr/bin/node
DAEMON_OPTS="/home/user/zero-ui/backend/bin/www"

export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"

export NODE_ENV=production
export ZU_SECURE_HEADERS=false
export ZU_SERVE_FRONTEND=true
export ZU_CONTROLLER_TOKEN=...
export ZU_DISABLE_AUTH=true
export ZU_DEFAULT_USERNAME=...
export ZU_DEFAULT_PASSWORD=...

case "$1" in
  start)
        echo -n "Starting daemon: "$NAME
    start-stop-daemon --start --quiet --pidfile $PIDFILE -m --exec $DAEMON --chdir /home/user/zero-ui/backend -- $DAEMON_OPTS
        echo "."
    ;;
  stop)
        echo -n "Stopping daemon: "$NAME
    start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
        echo "."
    ;;

  *)
    echo "Usage: "$1" {start|stop}"
    exit 1
esac

exit 0

Then I call it with the following script:

#!/bin/sh
set -e

ssh -n -L 127.0.0.1:3333:localhost:4000 user@server ./start-stop-zeroui start &
firefox localhost:3333/app
ssh user@server ./start-stop-zeroui stop
fg

If @larsks or anyone else comes up with a better answer I’ll gladly accept their answer, otherwise I’ll accept my own in a few days.

I upvoted @larsks because it sparked the idea.

Answered By: ZioByte