SSH Tunnel: Local and Remote Port Forwarding
About SSH
ssh stands for Secure Shell. It is a protocol used to securely connect to a remote server/system. ssh is secure in the sense that it transfers the data in encrypted form between the host and the client. For deep learning researchers, they usually use ssh to login their remote servers which have high-performance GPUs to train models. Besides its normal usage, it can be used to build tunnel to achieve local port forwarding and remote port forwarding (i.e. forwarding connections to port ssh
command is convenient to achieve these functions.
Local Port Forwarding
Local port forwarding is used to forward connections on a local port to another remote port on a different machine. Then all requests to the local port will be sent to the remote port by ssh tunnel.

Saying that we have a web server running in machine https://IP_of_machine_B:port
in the browser URL bar, the connection will be refused of course. Then we need local port forwarding.
The syntax of ssh local port forwarding is :
ssh -fNTL local_port:remote_host:remote_port user@ssh_host
-f
means let ssh to go to background just before command execution. So when type this command in local shell and type ENTER, it will return to the shell and we can do other things.-N
means do not execute a remote command. This is useful for just forwarding ports.-T
means disable pseudo-terminal allocation and it will save resource on both local and remote machine.-L
is the main parameter and it is used for Local port forwarding. Connections tolocal_port
on localhost will be forwarded toremote_port
onremote_host
byssh_host
. Theremote_host
we want to request can be the same asssh_host
or not.For example, we have an application running in a host named
app.com
on port 8888, which is accessible only from thessh_host
server. Then we can request this application byssh -fNTL 9999:app.com:8888 user@ssh_host
. In this way, we typehttps://127.0.0.1:9999
on wer local browser URL bar and the connection will get forwarded toapp.com:8888
byssh_host
and we’ll visit the application successfully.
E.g. Visit Remote Tensorboard
Tensorboard is an amazing tool to visualize the process of neural network model training. Training models in a remote server with high-performance GPUs but no GUI is familiar to DL researchers, and the tensorboard application will be deployed in the remote server, which cannot be visited by IP and port from our local browser (we don’t consider the tensorboard settings which may change its accessibility).
Suppose the remote server named gpu_server
and tensorboard listen on port 6006
. We can login the server as user yy
. So the command we used is:
ssh -fNTL 16006:localhost:6006 yy@gpu_server
When we type https://127.0.0.1:16006
in the browser URL bar, the connection to our localhost on port 16006 will be forwarded to gpu_server:6006
by gpu_server
. In this way, we establish a connection between our local browser and remote tensorboard service, but the remote tensorboard service only knows that the requests are from localhost (gpu_server
) which has access permission.
Remote Port Forwarding
In contrast to local port forwarding, remote port forwarding aims to forward connections on remote server to our local machine. This is useful when we want to communicate with a server in a local-area network by a machine in the public network.

The syntax of ssh remote port forwarding is :
ssh -fNTR remote_port:localhost:local_port user@ssh_host
-R
is the main parameter and it is used for Remote port forwarding. Connections toremote_port
onssh_host
will be forwarded tolocalhost:local_port
. Similar to local port forwarding, thelocalhost
in the command can be replaced by othernearhost
which can be connected from our localhost machine.
Note: When using remote port forwarding we need to add (or edit) GatewayPorts yes
to /etc/ssh/sshd_config
and restart the SSH daemon use sudo systemctl restart sshd
on the ssh_host
.
E.g. Intranet Penetration
Usually, we may have a server in wer workplace like school or company, and it can only be connected in local-area network because it doesn’t have a public network IP address. Even if we know the public IP address of wer workplace, we still can’t connect to the server by public_IP:port
for NAT exists. we need to deploy an intranet penetration in advance when we want to connect to the server from home or on vacation.
Suppose:
ID | location | IP address | login user name | description |
---|---|---|---|---|
machine_A | local area network | 10.109.244.100 | user_A | target server |
machine_B | public network | 39.97.183.218 | user_B | jump server |
machine_C | public network | 103.121.208.230 | user_C | wer local machine |
- When we are in local-area network, login machine_A as user_A and type
ssh -fNTR 2345:localhost:22 user_B@39.97.183.218
in terminal. This will establish a connect between machine_B and machine_A and connections tomachine_B:2345
will be forwarded tomachine_A:22
. - In machine_B we should (or edit)
GatewayPorts yes
to/etc/ssh/sshd_config
and restart the SSH daemon usesudo systemctl restart sshd.service
. In machine_B runnetstat -ntlp
we will see port 2345 has been listened. But it will be127.0.0.1:2345
which means only receive connections from localhost. If we runssh user_A@39.97.183.218 -p 2345
in machine_C directly, we will receive aConnection refused
message. But in machine_B, just runssh user_A@localhost -p 2345
we can login machine_A successfully. - If we want to connect to machine_A directly:
- Option 1: Run
ssh -fNTL *:4567localhost:2345 localhost
in machine_B. Then typenetstat -ntlp
we will see0.0.0.0:4567
which means port 4567 can receive connections from anywhere. Then we can runssh user_A@39.97.183.218 -p 4567
to login machine_A successfully. - Option 2: Change command in step 1 to
ssh -fNTR *:2345:localhost:22 user_B@39.97.183.218
. In machine_B we runnetstat -ntlp
and will see0.0.0.0:2345
has been listening, which means we can runssh user_A@39.97.183.218 -p 2345
to connect to machine_A directly.
- Option 1: Run
- SSH connection is unstable and will be closed if not be used for a long time. So we use
sutossh
to re-connect when the connection closed. The command we run in machine_A changed tosutossh -M 5566 -fNTR (*:)2345:localhost:22 user_B@39.97.183.218
.-M
means to specify a monitor port to check the connection status. When usingautossh
, we’d better runssh-copy-id user_B@39.97.183.218
to copy the key to machine_B which makes sure we can login machine_B from machine_A without password.
Q.A.
Reference:
https://unix.stackexchange.com/questions/46235/how-does-reverse-ssh-tunneling-work
https://blog.jakuba.net/ssh-tunnel---local-remote-and-dynamic-port-forwarding/