Tag Archives: ssh

Multiple SSH port-forwards, all in a row…

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:

Diagram of a complex SSH forwarding situation

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 (server-d.example.com:8080).

Now Server A can point to it’s localhost:8080, and end up on server-d.example.com:8080.

Spiffy, huh!

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.

Hacky IP forwarding with IP aliases and SSH

We interrupt your regularly scheduled broadcast of quality sysadmin programming to bring you a brief announcement on using SSH and hacky port forwards to access something via a LAN IP over the Internet.

If I have a server at home that can _only_ be accessed via 192.168.1.12 (say) – perhaps because it is a web application that rewrites all internal URLs to always go to that IP – how do I get access?

Easy. My application listens on 192.168.1.12:8888, so I’ll give it exactly that:


ip addr add 192.168.1.12/32 dev lo
ssh -L 192.168.1.12:8888:192.168.1.12:8888 user@example.net

So, I add 192.168.1.12/32 as a local IP address, bind SSH to it, forward all packets for 192.168.1.12:8888 over the SSH tunnel to the gateway server (example.net for this example), then it unbundles it from the SSH stream and passes it to the real 192.168.1.12.

It only works for that one port on that one IP address (though you can add individual IPs and ports easily enough!), but the key part is that it works.

To clean up, close your SSH links and run:


ip addr del 192.168.1.12/32 dev lo