Reverse SSH tunnels for remote port forwarding
- Configure SSH Servers
- Establish Tunnel
- Access Published Service
- Run tunnels in the background
- Use With Caution
Here's how to leverage reverse SSH tunnels to access hosts behind a firewall and/ or (CG)NAT over a public network.
external host | internal network
|
example.com | 192.0.2.50
------------ | ------------ --------------
|ssh-server| | |ssh-client| |winrdp:3389 |
|(ext. IP) |<--ssh--|(int. IP) |--lan--|(int. IP) |
------------ | ------------ --------------
A | B C
"Broker" "Jumphost" "Target"
Configure SSH Servers
To allow (remote) port forwarding, set these two options in /etc/ssh/sshd_config
both on Broker (A) and Jumphost (B):
GatewayPorts yes # Allow remote hosts to connect to forwarded ports
AllowTcpForwarding yes # Allow TCP forwarding
Gateway ports
can be omitted on Jumphost (B) if all you need is to reach services that are running directly on it.
Establish Tunnel
The ssh-client command is executed on host B ("Jumphost"):
jumphost$ ssh user@example.com -N -R 5000:192.0.2.50:3389
^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^
B A C
ssh
- Invoke ssh-clientuser@example.com
- Connect to Broker (A)-N
- Do not start a shell-R
- Provide a reverse tunnel5000:192.0.2.50:3389
forward all traffic that arrives on Broker (A) port 5000 to Target (C) port 3389.
Access Published Service
Use any independent host that is able to reach Broker (A) and access a service (Windows RDP in this example) running on Target (C):
mstsc /v example.com:5000
If a service (e.g. a local web server) that you want to make reachable is running directly on Jumphost (B), just use localhost
instead of Target's (C) IP address:
jumphost$ ssh -N -R 7000:localhost:80 user@example.com
Run tunnels in the background
The example above runs the SSH command in the foreground of your TTY, blocking your session on the jumphost. To continue working on the jumphost, e.g. to spawn more tunnels, consider using the ControlMaster & ControlPath functionality of SSH:
-f
- Requests ssh to go to background-M
- Places the ssh client into ''master'' mode for connection sharing-S
- Specifies the location of a control socket for connection sharing
See man ssh_config
paragraphs ControlMaster & ControlPath for more information.
Example:
jumphost$ ssh user@example.com -f -M -S ~/session1 -N -R 5000:192.0.2.51:3389
jumphost$ ssh user@example.com -f -M -S ~/session2 -N -R 5000:192.0.2.52:3389
To close the tunnels:
jumphost$ ssh -S ~/session1 -O exit example.com
jumphost$ ssh -S ~/session2 -O exit example.com
Instead of using session1
etc. as filenames for the sockets, I like to use the hostnames of my targets.
Use With Caution
Internal services are usually not ment to be publicly reachable.
Firewalling Broker (A) to only allow connections to forwarded ports (:5000) from trusted sources substantially minimizes risks here.
Also may consider to use e.g. a shell script that removes tunnels nightly or something like this..