›INDEX
Last Updated:

SSH Port Forwarding For Remote Access

An ssh port forwarding connection allows us to access machines that are not on the internet publicly (without a static public IP address) through another machine that is. If you've ever used Ngrok to connect to your local machine from the internet, this serves a similar purpose. I found this solution as an alternative to Ngrok.

Using the -R flag in ssh, we can accomplish this by forwarding all the traffic on a particular port on the remote machine to our current machine.

The Basic Command

ssh -R <Remote Port>:localhost:<Local port> -N <remote username>@<remote ip address>

NOTE: For the above command to work, you must change a setting in your sshd_config file to allow GatewayPorts. We can do this by opening the file /etc/ssh/sshd_config and changing the line that contains GatewayPorts to say: GatewayPorts yes.

Here's an example of that command that I run:

ssh -R 7247:localhost:22 -N suchi@suchicodes.com

The above command forwards all the traffic on port 7427 on my remote machine (my VPS) to port 22 on my current machine. Once this has started we can run something like:

ssh suchi@suchicodes.com -p 7427

This command will now connect to the remote machine (VPS), which will forward that request to the local machine you ran the command on.

The -R flag specifies a remote port forward. The -N specifies to not execute a remote command (useful for forwarding ports.)

Setting Up A Script

Everything is better when it's a script! We can set up a script that sets up the ssh connection, and if it happens to die for some reason, then it launches it again.

Here's the script:

#!/bin/sh

# Author: Suchith Sridhar
# Website: https://suchicodes.com
# Date: 20th Dec 2022

# Note: to run the script, you'll have to add your ssh key to
# the list of authorized hosts, else you'll have to type the
# password every time the ssh command is run.

# seconds to wait before checking again
sleep_interval=10

# log file to log ssh command output
log_file=/home/suchi/ssh-suchicodes.log

# can be IP or domain name
remote_ip=0.0.0.0

# remote username for login
remote_user=suchi

# remote port to be used for ssh forwarding
# Note that you will have to allow tcp/ip traffic on this port
remote_port=7327

# local port to be forwarded to
local_port=22

printed=0
while true
do
    exist=`ps aux | grep $remote_user@$remote_ip | grep $local_port`
    if test -n "$exist"; then
        if test $printed -eq 0; then
            echo "SSH connection active since: $(date)"
        fi
        printed=1
    else
        printed=0
        echo "SSH connection not active $(date)"
        echo "SCRIPT: Starting new connection on $(date)" >> $log_file
        ssh -R $remote_port:localhost:$local_port -N $remote_user@$remote_ip -v >> $log_file 2>&1
    fi
    sleep $sleep_interval
done

This script manages the ssh connection and ensures it's always active. You need to update the variables present before the loop, and each has a comment describing its purpose.

A Script For The Script?!

We want to launch the above script in the background so it can do its thing. So, I created a script that does exactly that.

#!/bin/bash

# Author: Suchith Sridhar
# Website: https://suchicodes.com
# Date: 20th Dec 2022

# This is the path of the previous script
# I recommend putting in ~/.local/bin
# I recommend a name like: open-from-<domain_name>.sh
PATH_OF_SCRIPT=/home/suchi/.local/bin/open-from-suchicodes.sh

# kill all existing script
pkill -f `echo $PATH_OF_SCRIPT | rev | cut -d "/" | rev`

echo "Launching script, log file: <name of current logfile> and <name of ssh logfile>"
bash $PATH_OF_SCRIPT >> <logfile> 2>&1 &
echo "Launch complete." 

Assuming we called this script reverse-ssh-script.sh, we can just run this single script once, and it should handle everything else.

I've also added this line into my crontab file using crontab -e: @reboot /home/suchi/.local/bin/reverse-ssh-script.sh so that this script is run as soon as the system starts up.

Enjoy the notes on this website? Consider supporting me in this adventure in you preferred way: Support me.