Sometimes, you really need to get from point “A” to point “B”, but you can’t. Restrictive firewalls, poor change control, you don’t own the infrastructure, or maybe it’s just “temporary” and you don’t want to have to go to all that effort just for a few days.
Struggle no more!
SSH Port Forwarding Primer
Let’s just say that you have an application on server “A”, and you want it to be able to reach a web service on your local desktop. You want to open a socket listening on the Remote end, which forwards the connection back over SSH to your local machine. (Maybe a NAT gateway is in the way).
Assuming the server is called “server-a” and your web service is on port 8080, the following may well suffice:
ssh -R8080:localhost:8080 server-a.example.com
“-R” for Remote listening socket, the port number for the designated [remote, in this case] side, then a host and port on the other [local] side.
If you want a local listening socket to forward the packets securely to the remote server – maybe a firewall is in the way this time – just change the Remote for Local:
ssh -L8080:localhost:8080 server-a.example.com
Now, connecting to your desktop’s port 8080 will land on the far-end’s
localhost:8080. Again, the first 8080 is for the designated side [local, this time] and the
localhost:8080 for the other [remote] side.
Linking port-forwards together
Here’s a hypothetical scenario, where Server D needs to be reached by Server A. For whatever reason, no single host has connectivity the whole distance.
In short, if an SSH port forward opens a remote socket and sends it locally, then that local port can be opened by a different SSH session and forwarded elsewhere too.
You can set this example up thusly:
On the desktop:
ssh -R8080:localhost:8080 server-a.example.com ssh -L8080:localhost:8080 server-b.example.com
These two together gets Server A connectivity to Server B (via port 8080). Right now, it ends there, because Server B isn’t listening on port 8080.
On Server B:
ssh -L8080:server-d.example.com:8080 server-c.example.com
This time, we don’t want to forward the local socket’s connections to
localhost on the remote server, we want to pass it all the way to Server D. What happens is that Server B listens on port 8080, bundles all the data up and over SSH to Server C, then Server C unpacks it all and sends it to the nominated address (
Now Server A can point to it’s
localhost:8080, and end up on
Please don’t do this in production, though – but if you do, please don’t tell anybody I told you how! :)
You might also be interested in [my other SSH port-forwarding hacky trick], where I show how to make a remote server appear local without needing proxy support in your application.