Using trap to automatically close a SSH tunnel

· 2min · Calvin Yong
Table of Contents

In my article on SSH port forwarding, we used SSH local forwarding to connect to a port on a local machine to a port on a remote machine to access services that would normally be restricted to localhost. But what if we wanted to automatically close the SSH process when we are done using a service like VNC? If we use ssh -N -L 5900:localhost:5900 remote; vncviewer localhost, the SSH process blocks us from running the vncviewer command. If we use ssh -N -L 5900:localhost:5900 remote &; vncviewer localhost, our VNC viewer will run, but if we close it, the SSH process will still be in the background. One way to automatically close the SSH process when the VNC viewer exits is by using the trap shell builtin command. Place the following into a script:

#!/usr/bin/env bash

trap 'kill $(jobs -p)' EXIT

ssh -N -L 5900:localhost:5900 remote &
# Tune the value based on how fast the ssh connection gets establishes
sleep 1.5
vncviewer localhost

First, we run the SSH local forwarding command as a background process. However, it may take some time for the connection to be established (e.g. if you use a slow key type like rsa4096), so we add a sleep command before running the vncviewer command. When we exit the vncviewer comamnd, and hence exit the script, the trap command will run kill $(jobs -p), which will send a SIGTERM signal to the SSH process and stop it.

Extra

If you want to log to the systemd journal when you open and close the SSH local forwarding, you could try using systemd-cat like the following:

trap 'systemd-cat -t name-of-script echo "Ending SSH port forward"; kill $(jobs -p)' EXIT

systemd-cat -t name-of-script echo "Starting SSH port forward"
ssh -N -L 5900:localhost:5900 remote &
sleep 1.5
vncviewer localhost

Or you can try using notify-send to send notifications to your desktop.

Resources