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
- 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;
- SSH_REVERSE_REMOTE_TUNNEL_PORT is the port you will connect to after the tunnel is UP to access the internal server port;
- 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);
- 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;
- 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;
- 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.
Cobbled together from these two helpful webpages: https://www.xmodulo.com/access-linux-server-behind-nat-reverse-ssh-tunnel.html
https://gist.github.com/drmalex07/c0f9304deea566842490
https://gist.github.com/drmalex07/c0f9304deea566842490