SSH Reverse Tunnel systemd Setup

Ever felt the need to have an SSH reverse tunnel setup so that it always starts on boot and stays up? And because we use a systemd template file, it is possible to have more than one reverse ssh tunnel configured, running and connected for different ports to different hosts. Here's how:
 
Add/Edit the following line in /etc/ssh/sshd_config:
GatewayPorts clientspecified
 Then
systemctl restart sshd
 
Create a file for each relayhost you want to create a reverse tunnel for, /etc/default/ssh-reverse-tunnel@relayhost (change relayhost to a meaningful name) and put the following in it:
SSH_REVERSE_REMOTE_HOST="relayhost_dns_name_or_ip"
SSH_REVERSE_REMOTE_PORT="relayhost_ssh_port_to_connect_to"
SSH_REVERSE_REMOTE_USER="remoteuser_to_connect_as"
SSH_REVERSE_REMOTE_TUNNEL_PORT=":port_number_on_remotehost_to_use_to_access_local_host"
SSH_REVERSE_LOCAL_TUNNEL_PORT="localhost:local_port_number"
SSH_REVERSE_OPTIONS="-v"
where
  1. SSH_REVERSE_REMOTE_HOST is available from the public internet with an SSH port (SSH_REVERSE_REMOTE_PORT) open. This is used to establish the tunnel only;
  2. SSH_REVERSE_REMOTE_TUNNEL_PORT is the port you will connect to after the tunnel is UP to access the internal server port; 
  3. SSH_REVERSE_REMOTE_USER is the remote user to use to access the remote relayhost. N.B. This assumes you have already setup public key-based authenticated (i.e. non-interactive) login for this user (see here);
  4. SSH_REVERSE_REMOTE_TUNNEL_PORT is the port that will be used to access the tunnel on the remote relayhost. This could be an SSH port but can be any port;
  5. SSH_REVERSE_LOCAL_TUNNEL_PORT is the port that will accessed on the local host thru the tunnel from the relayhost. This could be an SSH port but can be any port;
  6. SSH_REVERSE_OPTIONS are any other options you want to pass to ssh apart from whats listed in the systemd template service file (/etc/systemd/system/sh-reverse-tunnel@.service).
 
Then create an /etc/systemd/system/ssh-reverse-tunnel@.service template file with the following in it (This only needs to be done once, due to it being a systemd template file, denoted by the @ in the service filename):
[Unit]
Description=Reverse SSH Tunnel Connection @ %I
After=network.target

[Service]
EnvironmentFile=/etc/default/ssh-reverse-tunnel@%i

ExecStart=/usr/bin/ssh $SSH_REVERSE_OPTIONS -N -o StrictHostKeyChecking=no -o "ServerAliveInterval 10" -o "ExitOnForwardFailure yes" -p${SSH_REVERSE_REMOTE_PORT} -R ${SSH_REVERSE_REMOTE_TUNNEL_PORT}:${SSH_REVERSE_LOCAL_TUNNEL_PORT} ${SSH_REVERSE_REMOTE_USER}@${SSH_REVERSE_REMOTE_HOST}
Restart=always
RestartSec=5s

[Install]
WantedBy=default.target
 
Then reload the systemd daemon:
systemctl daemon-reload
Then, for each relayhost you have created in /etc/default, do the following:
systemctl enable --now ssh-reverse-tunnel@relayhost
With a bit of goodwill the reverse tunnel(s) should come up. If not, check your syslog (eg: /var/log/messages or /var/log/syslog). You can set SSH_REVERSE_OPTIONS="-vvv" in /etc/default/ssh-reverse-tunnel@relayhost to see more debugging info in the syslog.