When setting up remote port forwarding with SSH, you might encounter a situation where:
- The connection establishes successfully
- Local port forwarding appears to work
- But remote connections get refused
The key configuration parameters we're dealing with:
# /etc/ssh/sshd_config
GatewayPorts clientspecified
And the SSH command used for forwarding:
ssh -g -R 1234:0.0.0.0:8000 me@my-remote-host
Checking what's actually listening after establishing the connection:
netstat -tupln | grep 1234
tcp 0 0 127.0.0.1:1234 0.0.0.0:* LISTEN
tcp6 0 0 ::1:1234 :::* LISTEN
Notice how it's only binding to localhost (127.0.0.1 and ::1) despite the -g flag and GatewayPorts setting.
The issue stems from a common misunderstanding of how GatewayPorts
interacts with -R
binding behavior. Even with:
GatewayPorts clientspecified
in sshd_config- The
-g
flag on the client
The binding still defaults to localhost unless explicitly specified in the -R
parameter.
The correct SSH command should specify the bind address in the remote portion:
ssh -R *:1234:0.0.0.0:8000 me@my-remote-host
Or for IPv6 support:
ssh -R [::]:1234:0.0.0.0:8000 me@my-remote-host
After establishing the connection, verify with:
ss -ltn | grep 1234
# Should show:
LISTEN 0 128 *:1234 *:*
For permanent solutions, consider adding to your SSH config:
Host my-remote-host
RemoteForward 1234 0.0.0.0:8000
GatewayPorts yes
Then simply connect with:
ssh my-remote-host
When exposing ports to public interfaces:
- Use firewall rules to restrict access
- Consider using SSH's
AllowTcpForwarding
in sshd_config - Implement authentication on your forwarded service
When setting up SSH remote port forwarding (-R
flag), you might encounter a situation where:
- The tunnel appears to establish successfully
- Local connections to the forwarded port work
- Remote connections get "Connection Refused"
From your debug output and configuration:
# Relevant sshd_config setting
GatewayPorts clientspecified
# SSH command used
ssh -g -R 1234:0.0.0.0:8000 me@my-remote-host
# Netstat output showing binding
tcp 0 0 127.0.0.1:1234 0.0.0.0:* LISTEN
tcp6 0 0 ::1:1234 :::* LISTEN
The issue stems from how SSH binds the remote port. Despite using -g
(allows remote hosts to connect) and GatewayPorts clientspecified
, the port is still binding to loopback addresses (127.0.0.1 and ::1).
Solution 1: Explicit Bind Address
ssh -R *:1234:0.0.0.0:8000 me@my-remote-host
Solution 2: Modify sshd_config
# In /etc/ssh/sshd_config
GatewayPorts yes
Then restart SSH:
sudo systemctl restart sshd
- Check the binding after establishing the tunnel:
sudo netstat -tulnp | grep 1234 # Should show 0.0.0.0:1234 instead of 127.0.0.1:1234
- Test remote connectivity:
curl -v http://my-remote-host:1234
If the issue persists:
# Check system-level firewall
sudo iptables -L -n -v
# Check TCP wrappers
sudo lsof -i :1234
# Verbose SSH logging
ssh -vvv -R *:1234:0.0.0.0:8000 me@my-remote-host
When opening ports to all interfaces:
- Consider firewall rules to restrict access
- Use SSH key authentication exclusively
- Monitor connection attempts
- Consider using VPN for sensitive applications
For complex networking scenarios:
# Using autossh for robust tunnels
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-N -R *:1234:localhost:8000 me@my-remote-host