Reverse SSH tunnel
The remote port forwarding capability (also known as reverse tunneling) provided by SSH is opposite to that of the direct SSH tunnel.
A reverse SSH tunnel, also known as remote port forwarding, allows the creation of a tunnel that redirects traffic from a remote server and port, to a specified port on the local machine, via an SSH connection.
Note: The terms reverse tunnel and remote port forwarding will be used interchangeably.
Reverse tunneling is enabled with the -R
flag, with the supplied values: [remote_address:]remote_port:local_address:local_port
Use case
The SSH reverse tunnel can be utilized to expose a locally running service to the internet (without the need to manually setup port forwarding on the gateway).
For example, suppose there is a workstation running certain services on port 3389 (Remote Desktop Protocol) and 22 (SSH) that is required to be accessed from the internet. However, this workstation is behind a managed secure network that he/she is not in direct control of (eg. school campus network), and it is not practical to approach the network administrator to enable port forwarding on the internet-facing gateway. Along with additional access to a remote SSH server, a reverse tunnel can be used in this case.
Let's assume the situation:
Machine A: remote SSH server (eg. AWS EC2) with a public address of 11.11.11.11 present on a network environment where port forwarding rules can be added on the internet-facing gateway
Machine B: workstation (behind the managed network) running RDP/SSH on port 3389/22 respectively
Machine C: client on the internet to access the services on machine A
Machine A
Enable and start the SSH daemon (SSHD) is running:
Enable GatewayPorts (not the safest method ~ continue reading about the commands for machine C for more information)
Port forwarding requirements on the internet-facing gateway
Let's assume beforehand that the entry ports to the reverse tunnel on machine A are 8888 and 6666, that will be routed to ports 3389 and 22 respectively. In this case, a port forwarding rule is needed to be made on the internet-facing gateway: mapping 2 ports of choice on the public address (assume 8866 and 6688), to local ports 8888 and 6666 respectively as follows:
~ Assuming the LAN address of machine A is 192.168.1.80
11.11.11.11:8866 -> 192.168.1.80:8888 -> 127.0.0.1:8888 (entry point to the reverse tunnel)
11.11.11.11:6688 -> 192.168.1.80:6666 -> 127.0.0.1:6666 (entry point to the reverse tunnel)
... explanation of why GatewayPorts is needed
Machine B
Send a remote port forwarding request to machine A
Note: Basic SSH command flags (such as -i) will be omitted, only the relevant one will be included:
This command bind the ports 8888 and 6666 on 11.11.11.11 (machine A) to the localhost address on port 8888 and 6666 on machine B, respectively. This essentially allows traffic to be sent to the RDP and SSH ports on machine B from the remote forwarded ports on machine A (8888 and 6666).
Machine C
Suppose the GatewayPorts setting is configured correctly, and the public-to-private addresses port forwarding on the internet-facing gateway is configured correctly. From machine C, the services port on machine B can be accessed via the public address of machine A at 11.11.11.11 as follows:
RDP: 11.11.11.11:8866 (machine A) -> 192.168.1.80:8888 (machine A) -> 127.0.0.1:8888 (machine A) -> 127.0.0.1:3389 (machine B ~ RDP)
SSH: 11.11.11.11:6688 (machine A)> 192.168.1.80:6666 (machine A) -> 127.0.0.1:6666 (machine A) -> 127.0.0.1:22 (machine B ~ SSH)
Eg. Accessing a SSH shell on machine B:
Notice that the user to connect to is the one on machine B, rather than on machine A.
Another safer alternative to access the services running on machine B is to directly send a local port forwarding connection via SSH to machine A:
Notice that the user to connect to is the one on machine A, not machine B.
The services on machine B can be accessed via localhost ports 8866 and 6688 on machine C locally instead, without the need of exposing ports 8866 and 6688 on machine A (11.11.11.11) as follows:
127.0.0.1:8866 (machine C) -> 127.0.0.1:8888 (machine A) -> 127.0.0.1:3389 (machine B ~ RDP)
127.0.0.1:6688 (machine C) -> 127.0.0.1:6666 (machine A) -> 127.0.0.1:22 (machine B ~ SSH)
Thus, the port forwarding rules on the internet-facing gateway in machine A's network environment can be disabled, along with GatewayPorts:
Overview of benefits of this method:
Prevent over-exposure of public facing ports on machine A without a proper authentication mechanism - anyone on the internet can access the ports and gain access to the services running on machine B. This can lead to unauthorized access, assuming that IP whitelisting is not enabled.
Only port 22 (SSH) machine A will be exposed to the internet. This provides an authentication mechanism that is provided by SSH
Eg. Accessing a SSH shell on machine B:
Notice that the user to connect to (supplied as the user value in the format: <user>@address
) is the one on machine B, rather than on machine A.
Last updated