SSH Tunneling Lab – Local and Remote Port Forwarding

SSH tunneling lab for penetration testing. Practice local (-L) and remote (-R) port forwarding with Docker. Pivot through a jump host to reach internal MySQL and receive reverse shells.

Introduction

Repo⭐ Please give a Star if you enjoyed this lab ⭐
DownloadsGitHub Clones
StarsGitHub Repo stars
PrerequisitesDocker-ce, mysql-client
DifficultyStatic Badge

This lab demonstrates SSH tunneling and pivoting. You have SSH access to a jump host (pivot) that can reach an internal server; in a real engagement, only the pivot would have that access. You will use local port forwarding (-L) to reach the internal MySQL server through the pivot, and remote port forwarding (-R) to receive a reverse shell from the internal server through the pivot. For more on the concepts, see SSH Tunneling.


Lab Environment

DescriptionHostnameExternal IPInternal IPPortCredentials
Jump / Pivotpivot172.26.0.10192.168.50.222pivotuser:PivotPass123
Internal serverinternal192.168.50.1022, 3306internaluser:InternalPass123 (SSH), root:MySQLRootPass123 (MySQL)

Setup

Clone the repository:

git clone https://github.com/rootandbeer/ssh-tunneling-lab
cd ssh-tunneling-lab


Start the environment:

docker compose up -d

Objective 1 – Local Port Forwarding (reach MySQL via pivot)

Goal: Connect your MySQL client to the internal server at 192.168.50.10:3306 by tunneling through the pivot.

How it works: You run ssh -L on your host. That opens port 13306 on your host. When you connect to 127.0.0.1:13306 with the MySQL client, SSH sends that traffic through the tunnel to the pivot, and the pivot connects to 192.168.50.10:3306.


Summary: Your host (127.0.0.1:13306) → SSH tunnel → pivot → 192.168.50.10:3306 (MySQL).


Objective 2 – Remote Port Forwarding (reverse shell from internal server)

Goal: Get a reverse shell from the internal server (192.168.50.10) to your host by forwarding a listener through the pivot.

How it works: You run nc on your host on port 9444. You run ssh -R so the pivot listens on 4444 and forwards to your host:9444. The internal server connects to the pivot at 192.168.50.2:4444; the pivot sends that through the tunnel to your listener.

This uses 3 terminals:


You should get a shell in terminal 1 where nc -lvnp 9444 is running on your host.

Summary: 192.168.50.10 → 192.168.50.2:4444 (pivot) → SSH tunnel → your host:9444.


Cleanup

Stop and remove the Docker containers:

docker compose down


To remove the MySQL data volume as well:

docker compose down -v


⭐ Please give a Star if you enjoyed this lab ⭐

Saturday, February 7, 2026 Friday, February 6, 2026