SSH Tunneling

When you need to access a server/client behind a firewall that doesn’t allow port forwarding you can use SSH tunneling to bypass that if an SSH server is running. Pivoting is a sneaky technique that hackers use to access computers, servers, and services behind firewalls. These examples will use OpenSSH. I think most examples don’t explain this well and I’m hoping that this makes it clear.

SSH Commands

-D: [bind_address:]port
-f: runs the SSH client in the background.
-g: use gateway ports
-N: disables a shell prompt after connecting.
-R: reverse option.
-T: disabled pseudo-TTY.


Jump Server: There’s really nothing special about this other than this is the server that we will be passing through using SSH tunneling.

Local Port Forwarding

Local port forwarding can allow you to access services behind a firewall. For example, if you want to access a website that is not being served in the DMZ local port forwarding will allow you to access that remotely.

This can be tried out on VulnHub: Symfonos 2. This VulnHub has a LibreNMS running on port 8080 behind the firewall.

Website Hosted on Port 8080 Behind Firewall

ssh -Ngf -L 8080: [email protected]

This will forward port 8080 on my local machine (Parrot OS) and allow me to browse the website that is behind the firewall on port 8080 on server

Reverse Port Forwarding

Imagine I want to remotely access my home computer that sits behind a firewall. Instead of enabling ports through the router/firewall an alternative would be to use a jump server (Digital Ocean Droplet) and create a reverse port forwarding through SSH tunneling. This also works with VPNs that don’t allow port forwarding.

To start with I will use a Digital Ocean server as a jump server. Then I will use a Virtual Machine running Parrot OS 4.7 to connect to that jump server to access my home machine (Windows 10). Since my Parrot OS VM will be getting it’s IP from my router this will simulate a real-life example.

Demo: In this example, I will host a website on port 8000 on my laptop and view that website on my Parrot OS VM through a jump server on Digital Ocean. I am using a standard Ubuntu droplet with no modifications.

ssh -R remote_port:local_address:local_port [email protected]

Digital Ocean Droplet’s (Jump Server) IP:

On my local machine (laptop), I will connect to the jump server and create a reverse port forwarding tunnel.

ssh -R 8080: [email protected]

On my Parrot OS virtual machine, I will connect to the Digital Ocean jump server using SSH.

ssh [email protected]

# once connected to the jump server I will connect to my local machine through the reverse tunnel

# this should return the html from the website running on my laptop.
(Parrot OS VM)

Exposing it Out with GatewayPorts

At this point, I’m not able to access the website through a browser on my Parrot OS VM.

On the Digital Ocean jump server, you will need to allow port 8080 through the firewall and adjust the SSH configuration.

# allow port 8080 through firewall
sudo ufw allow 8080

GatewayPorts – This is a configuration in SSH that needs to be enabled for ports to be exposed externally. This is located in the file /etc/ssh/sshd_config.conf

(Enabling GatewayPorts in sshd_config)
# restart ssh daemon
sudo systemctl restart sshd

On my Windows 10 laptop, I will need to need to restart the SSH tunnel.

# windows 10 home laptop
ssh -R 8080: [email protected]


I can create a SOCKS proxy on port 1080 by running a command like below. I tried this out on a Digital Ocean server and it worked really well. I was able to run nmap with proxychains to scan internal ports.

ssh -D 1080 [email protected]

To do this make sure you only have this line in your /etc/proxychains.conf file.

socks4 1080

then you can run nmap against the internal web server by passing it through proxychains. This works better than using theproxy attribute in nmap.

proxychains nmap

Setting up an SSH Server in Parrot OS / Kali

You may find yourself in a situation where you have a reverse shell and need to forward ports to access an internal MySQL database because the MySQL client is not installed. I used this technique on Kioptrix #3.

Installing the SSH service

# installing latest ssh server
sudo apt update
sudo apt install openssh-server

# allow through firewall (or specify port if not using default 22)
sudo ufw allow ssh
# check status of ssh server
sudo systemctl status ssh

# start sshd
sudo systemctl start ssh

# disable during boot
sudo systemctl disable ssh

# enable sshd service
sudo systemctl enable ssh

Reverse Port Forward the MySQL Service

I created a user in Parrot OS / Kali and in the reverse shell I was able to tunnel out the MySQL port, and at that point, I could access the internal MySQL server using the credentials I found.

ssh -R 3306: [email protected]
(reverse shell using port forwarding to gain access to MySQL service)