An SSH reverse tunnel allows a local machine to access a remote port that is behind a firewall, NAT, or is otherwise unreachable over Internet (e.g. a MySQL database). The remote machine must connect to the local machine over SSH.

The process to set up a reverse tunnel is as follows: Start SSH server on local machine.

sudo systemctl start ssh

Create SSH key on remote machine

ssh-keygen # options...

Add the public key to local user’s authorized_keys. To restrict access to tunneling alone, use the following template (replace $REMOTE_IP with public IP address of the remote host):

from="$REMOTE_IP",command="false",no-agent-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4cjmvS... mysql@zora

Run the following on the remote machine (explanation below):

ssh -f -N -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -R $local_port:$remote_host:$remote_port $local_username@$local_host 
  • The “local” and “remote” in the above command is relative to the location of the user, not where the command is invoked.
  • -f: Run in background
  • -N: Do not try to start a shell
  • The -o options removes user interaction and avoids recording the host key
  • -R $local_port:$remote_host:$remote_port
    • $local_port: where SSH tunnel is opened on local machine
    • $remote_host: the IP address of the remote machine. Since the command is run on the remote host, it can be localhost or any of its interface addresses. This can even be another IP reachable by the remote client.
    • $remote_port: the port that the local user wishes to access
    • Multiple -R <args> can be specified to port-forward multiple remote ports
  • $local_username@$local_host: username and host of the local user/machine