Per Stenebo
2017-03-26 07:15:47
2018-03-13 20:37:28
SSH remote port forward
How to access a firewalled host from the outside with SSH, primarily aimed for GNU/Linux hosts with OpenSSH.
Ubuntu: | SSH manpage | ssh_config manpage | port forward |

Prerequisites
- SSH clients on both the source and target hosts.
- A working and public accessible ssh server at the source host.
- You can login by ssh from target to source host, like:
ssh -p 22 me@example.org
1. Create tunnel
From target host: Create SSH tunnel to source host:
Syntax: ssh -R "source local port":localhost:"source ssh-server port" -N "source-user"@"source.public.host"
Example:
ssh -R 9999:localhost:22 -N me@example.org -o "ExitOnForwardFailure yes"
If you get an error like "ssh: connect to host example.org port 22: Connection refused" and the source ssh-server private port differs from the public port, like if it is forwarded by a router/gateway/firewall, then you have to add the source ssh-server public port as an argument, like:
ssh -R 9999:localhost:22 -N me@example.org -p 1234
2. Use tunnel
You can check tunnel status from the source host with:
netstat -lnt
It returns all listening ports, there should be a line similar to this:
Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 127.0.0.1:9999 0.0.0.0:* LISTEN
The line tell us that the source host is listening for a TCP-connection on port 9999 from 127.0.0.1 (localhost) only.
From source host: Connect to target host thru the tunnel:
Syntax: ssh -p "local port" "target-user"@localhost
Example: ssh -p 9999 pro@localhost
Other use cases
Forward local HTTP port 80 on hostA to port 8080 on hostB. Issue SSH remote port forward command from a terminal on hostA:
ssh -R 8080:localhost:80 -N hostB
Then, from hostB, connect using a browser to http://localhost:8080
Notes
The port 9999 in the example above can be replaced by any available port number.
As mentioned above, you can only connect thru localhost on the source host. So if you wish to connect from another host it must go via source host. It can be done by for example ssh proxy or ssh local forwarding.
This method does not require that you have control over any firewalls on the target side, it's enough if they allow outgoing SSH traffic to the source host.
On Windows I think the SSH client Putty support remote forwarding too.
autossh
If your setup should live longer than a simple test a tool like autossh (man page) would keep the connection alive whenever possible. An example could be:
autossh -f -R 9999:localhost:22 -N me@example.org -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -o "ExitOnForwardFailure yes"
This assumes that you have setup automatic login with key authentication from the target to the source host. Remove option -f when testing manually to avoid sending autossh to background.
Restrict access
| Restrict SSH access to port forwarding to one specific port | Ubuntu ssh-keygen man page |
Troubleshooting
The logfiles are your friends: /var/log/syslog, /var/log/auth.log and possibly /var/log/fail2ban.log
Add the option -v to any ssh command to get verbose mode. Up to 3 "-v" are supported.