What's Actually Happening
You've set up an SSH reverse tunnel to expose a local service through a remote server, but when you try to connect to the tunnel from another machine, the connection fails. The tunnel appears to be running, but external connections are rejected or simply don't reach your local service.
The Error You'll See
When testing from another machine:
$ nc -zv remote-server.com 8080
nc: connect to remote-server.com port 8080 (tcp) failed: Connection refusedOr when checking on the remote server itself:
$ ss -tlnp | grep 8080
127.0.0.1:8080 LISTEN 1234/sshdNotice the tunnel is only listening on localhost (127.0.0.1), not on all interfaces.
Why This Happens
SSH reverse tunnels bind to localhost by default for security reasons. The GatewayPorts option in sshd_config controls whether tunnels can listen on all interfaces. When GatewayPorts no is set (the default), your tunnel only accepts connections from the remote server itself, not from external hosts.
Step 1: Check Current Tunnel Status
On the remote server, verify where your tunnel is listening:
ss -tlnp | grep <port>If you see 127.0.0.1:<port>, the tunnel is not accessible externally. You can also check active SSH tunnels:
netstat -tlnp | grep sshdStep 2: Enable GatewayPorts on the Server
Edit the SSH daemon configuration on the remote server:
sudo nano /etc/ssh/sshd_configAdd or modify this line:
GatewayPorts clientspecifiedThis allows clients to specify binding addresses. Then restart SSH:
sudo systemctl restart sshdStep 3: Create the Tunnel with Proper Binding
When establishing the reverse tunnel, specify that it should bind to all interfaces:
ssh -R 0.0.0.0:8080:localhost:3000 user@remote-server.comThe 0.0.0.0: prefix tells SSH to bind to all network interfaces, not just localhost.
Step 4: Verify the Tunnel Binding
On the remote server, check that the tunnel now listens on all interfaces:
ss -tlnp | grep 8080You should now see:
0.0.0.0:8080 LISTEN 1234/sshdStep 5: Test from External Host
From a different machine, test the connection:
curl http://remote-server.com:8080Or use netcat:
nc -zv remote-server.com 8080Verify the Fix
The tunnel is working correctly when:
- 1.
ss -tlnpshows0.0.0.0:<port>or:::<port>as the listening address - 2.External hosts can connect to the remote server on the forwarded port
- 3.Your local service receives the traffic
If you still have issues, check firewall rules on the remote server:
sudo iptables -L -n | grep 8080
sudo ufw statusAdd firewall rules if needed:
sudo ufw allow 8080/tcp