Reverse SSH tunnels explained
Topic: Networking basics
Summary
A reverse SSH tunnel lets a host behind NAT or a firewall initiate an SSH connection to a reachable server and expose a port on that server that forwards back to the host. Use when the target host cannot accept inbound connections (e.g. no public IP, firewall blocks). Conceptual only; server must allow remote forwards.
Intent: How-to
Quick answer
- The host that cannot be reached (e.g. behind NAT) runs ssh -R REMOTE_PORT:LOCAL_HOST:LOCAL_PORT SERVER. It connects out to SERVER; SERVER then listens on REMOTE_PORT and forwards traffic back through the tunnel to LOCAL_HOST:LOCAL_PORT on the initiator side.
- Use case: access a service (e.g. dev server, admin UI) on a machine that has no public IP or is behind a strict firewall. The machine opens the tunnel; you connect to SERVER:REMOTE_PORT and get the service. No inbound port open on the target.
- Server config: AllowTcpForwarding yes; for others to use REMOTE_PORT, GatewayPorts yes (or clientspecified). Restrict who can create remote forwards and which ports to avoid abuse.
Prerequisites
Steps
-
How the reverse forward works
Client (behind NAT or firewall) runs ssh -R REMOTE_PORT:LOCAL_HOST:LOCAL_PORT SERVER. The SSH connection is outbound from client to SERVER. On SERVER, sshd listens on REMOTE_PORT; traffic to SERVER:REMOTE_PORT is sent through the tunnel to LOCAL_HOST:LOCAL_PORT on the client. So the client never accepts inbound TCP; it only initiates.
-
When to use it
Use when the host with the service cannot accept inbound connections (no public IP, NAT, or firewall). The host opens the reverse tunnel; you (or a monitoring system) connect to SERVER:REMOTE_PORT to reach the service. Common for dev boxes, home servers, or temporary access.
-
Server-side requirements
AllowTcpForwarding yes. For others (not just the SSH user) to connect to REMOTE_PORT, GatewayPorts yes or GatewayPorts clientspecified; otherwise the bind is localhost-only. Restrict which users can use -R and which ports to reduce risk.
Summary
A reverse SSH tunnel is started by the host that cannot be reached: it connects out to a server and uses -R so the server listens on a port and forwards traffic back through the tunnel. Use it when the target has no public IP or cannot accept inbound connections. The server must allow remote forwards and optionally GatewayPorts for others to use the bound port.
Prerequisites
Steps
Step 1: How the reverse forward works
The client (behind NAT or firewall) runs ssh -R REMOTE_PORT:LOCAL_HOST:LOCAL_PORT SERVER. The SSH connection is outbound. On the server, sshd listens on REMOTE_PORT; traffic to SERVER:REMOTE_PORT is forwarded through the tunnel to LOCAL_HOST:LOCAL_PORT on the client. The client never accepts inbound TCP.
Step 2: When to use it
Use when the host with the service cannot accept inbound connections. That host opens the reverse tunnel; you connect to SERVER:REMOTE_PORT to reach the service. Typical for dev boxes, home servers, or temporary access.
Step 3: Server-side requirements
AllowTcpForwarding yes. For others to connect to REMOTE_PORT, set GatewayPorts yes or clientspecified; otherwise the bind is localhost-only. Restrict which users and ports can be used for -R.
Verification
You can explain why the initiator is the host behind NAT and how traffic flows from SERVER:REMOTE_PORT to the client; you know the required server options.
Troubleshooting
Cannot connect to SERVER:REMOTE_PORT — Check GatewayPorts; check firewall on SERVER for REMOTE_PORT; ensure the tunnel is up (ssh -R session alive). Tunnel drops — Use autossh or a keepalive so the SSH session stays up; ensure the service on LOCAL_HOST:LOCAL_PORT is listening.