SSH Forward Tunneling Guide
Introduction
SSH forward tunneling (also known as local port forwarding) allows you to securely connect to a remote service through an SSH server, making it appear as if the service is running on your local machine. This is useful for accessing services on a remote server or another machine in a secure network that aren’t directly accessible.
In this guide, we’ll cover the basics of SSH forward tunneling, explain how it works, and provide practical examples.
What is SSH Forward Tunneling?
Forward tunneling lets you forward a local port to a remote server or another host reachable by the SSH server. The connection is encrypted through the SSH tunnel, ensuring secure communication.
Basic Syntax
ssh -L [local_port]:[destination_host]:[destination_port] [user]@[ssh_server]
-L: Specifies local port forwarding.[local_port]: The port on your local machine where you’ll access the service.[destination_host]: The target host (relative to the SSH server) you want to connect to.[destination_port]: The port on the destination host.[user]@[ssh_server]: The SSH server acting as the intermediary.
How It Works
- You initiate an SSH connection to the SSH server.
- A local port on your machine is bound to a specific port on the destination host via the SSH server.
- Any traffic sent to the local port is forwarded through the SSH tunnel to the destination host and port.
Prerequisites
- An SSH client installed (e.g.,
OpenSSHon Linux/macOS or tools like PuTTY on Windows). - Access to an SSH server with credentials (username and password or SSH key).
- Knowledge of the destination host and port you want to access.
Examples
Example 1: Accessing a Remote Web Server
Suppose you want to access a web server running on webserver.local (port 80) through an SSH server (ssh.example.com). The web server isn’t directly accessible from your machine, but the SSH server can reach it.
ssh -L 8080:webserver.local:80 user@ssh.example.com
- Explanation:
8080: Your local machine’s port where you’ll access the web server.webserver.local:80: The remote web server and its port.user@ssh.example.com: The SSH server you’re connecting to.
- Usage: Open your browser and go to
http://localhost:8080. The traffic is tunneled towebserver.local:80via the SSH server.
Example 2: Accessing a Database Server
You need to connect to a MySQL database running on dbserver.local (port 3306) through the same SSH server.
ssh -L 3306:dbserver.local:3306 user@ssh.example.com
- Explanation:
3306: The local port where you’ll connect your MySQL client.dbserver.local:3306: The remote MySQL server and its port.
- Usage: Use a MySQL client (e.g.,
mysqlor a GUI like DBeaver) to connect tolocalhost:3306. The traffic is forwarded to the remote database.
Example 3: Tunneling to Another Machine
If you want to access a service on a third machine (internal.host:5432) that’s only reachable by the SSH server, you can forward traffic like this:
ssh -L 5432:internal.host:5432 user@ssh.example.com
- Usage: Connect to
localhost:5432from your local machine to interact withinternal.host:5432.
Useful Options
Background Mode: Run the tunnel in the background with
-fand-N(no command execution):ssh -f -N -L 8080:webserver.local:80 user@ssh.example.comBind to All Interfaces: Allow other machines to connect to your local port (use with caution):
ssh -L 0.0.0.0:8080:webserver.local:80 user@ssh.example.comKeep Alive: Prevent the tunnel from timing out by adding keep-alive options:
ssh -o ServerAliveInterval=60 -L 8080:webserver.local:80 user@ssh.example.com
Practical Script
Create a script to set up a forward tunnel and verify it’s running:
#!/bin/bash
# ssh_tunnel.sh
echo "Setting up SSH forward tunnel..."
ssh -f -N -L 8080:webserver.local:80 user@ssh.example.com
if [ $? -eq 0 ]; then
echo "Tunnel established. Access the service at http://localhost:8080"
else
echo "Failed to establish tunnel."
fi
Make it executable:
chmod +x ssh_tunnel.sh
./ssh_tunnel.sh
Port Forwarding
Port forwarding with SSH comes in three main flavors: local, remote, and dynamic. Each serves a unique purpose for managing network access securely.
Local Forwarding
As described above, local forwarding (-L) allows you to access internal services from your local machine through an SSH server. It’s ideal for securely connecting to resources in a private network.
Example:
ssh -L 8080:internal.service:80 user@ssh.example.com
Access http://localhost:8080 to reach internal.service:80.
Remote Forwarding
Remote forwarding (-R) exposes a service running on your local machine (or a machine accessible by your local machine) to the SSH server or another machine reachable by the SSH server.
Syntax:
ssh -R [remote_port]:[local_host]:[local_port] [user]@[ssh_server]
Example:
ssh -R 8080:localhost:3000 user@ssh.example.com
- Explanation: A service running on your local machine at
localhost:3000becomes accessible on the SSH server atssh.example.com:8080. - Usage: From the SSH server or another machine that can reach it, access the service at
http://ssh.example.com:8080.
Dynamic Forwarding (SOCKS Proxy)
Dynamic forwarding (-D) turns your SSH connection into a SOCKS proxy, acting like a mini-VPN. It allows you to route traffic dynamically through the SSH server without specifying a fixed destination host or port.
Syntax:
ssh -D [local_port] [user]@[ssh_server]
Example:
ssh -D 1080 user@ssh.example.com
- Explanation: Creates a SOCKS proxy on
localhost:1080. Configure your browser or application to use this proxy, and traffic will be routed through the SSH server. - Usage: Set your browser’s SOCKS proxy to
localhost:1080to browse securely via the SSH server.
SSH as a VPN (Tunnel Layer 2 or 3)
SSH can be used to create a VPN-like tunnel at the network layer (Layer 2 or 3) using tools like sshuttle or by configuring a TUN/TAP interface. This allows entire network traffic to be routed through the SSH server.
Example with sshuttle:
sshuttle -r user@ssh.example.com 192.168.1.0/24
- Explanation: Routes traffic for the
192.168.1.0/24subnet through the SSH server, effectively creating a VPN.
X11 Forwarding (GUI Remote)
X11 forwarding allows you to run graphical applications on a remote server and display them on your local machine.
Syntax:
ssh -X [user]@[ssh_server]
Example:
ssh -X user@ssh.example.com xterm
- Explanation: Runs the
xtermapplication on the SSH server, but its GUI is displayed on your local machine. - Prerequisite: An X server (e.g., XQuartz on macOS or Xming on Windows) must be running locally.
Mounting a Remote Filesystem (sshfs)
With sshfs, you can mount a remote filesystem locally over SSH, allowing you to interact with remote files as if they were on your machine.
Example:
sshfs user@ssh.example.com:/remote/path /local/mountpoint
- Explanation: Mounts the
/remote/pathdirectory from the SSH server to/local/mountpointon your local machine. - Unmount: Use
umount /local/mountpointto detach.
Install sshfs:
sudo apt install sshfs # Ubuntu/Debian
Multiplexing Connections
SSH multiplexing allows multiple sessions to share a single SSH connection, reducing overhead for multiple tunnels or commands.
Example Configuration (~/.ssh/config):
Host ssh.example.com
ControlMaster auto
ControlPath ~/.ssh/mux-%r@%h:%p
ControlPersist 10m
Usage:
ssh user@ssh.example.com # Opens master connection
ssh user@ssh.example.com # Reuses existing connection
Reverse Shell Securely
A reverse shell can be established using SSH remote forwarding to allow a remote machine to access a shell on your local machine securely.
Example:
ssh -R 2222:localhost:22 user@ssh.example.com
- Explanation: From the SSH server, you can connect to
localhost:2222to access your local machine’s SSH server (localhost:22).
Pro Tips
Tip: Use autossh for a more robust tunnel that automatically reconnects if the connection drops:
autossh -M 0 -f -N -L 8080:webserver.local:80 user@ssh.example.com
Install autossh with:
sudo apt install autossh # Ubuntu/Debian
0.0.0.0, as it exposes the port to all network interfaces, potentially allowing unauthorized access.Troubleshooting
- Connection Refused: Ensure the SSH server can reach the destination host and port.
- Port Already in Use: Check if the local port is already used (
netstat -tuln) and choose another port. - Permission Denied: Verify your SSH credentials or key-based authentication setup.
- Tunnel Stops: Use
-o ServerAliveInterval=60to keep the connection alive or considerautossh.
Next Steps
In future tutorials, we’ll explore:
- Reverse SSH tunneling for exposing local services.
- Dynamic tunneling with SOCKS proxy.
- Advanced SSH configurations with
~/.ssh/config.
Resources
Practice setting up tunnels with different services to master SSH forwarding!