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

  1. You initiate an SSH connection to the SSH server.
  2. A local port on your machine is bound to a specific port on the destination host via the SSH server.
  3. 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., OpenSSH on 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 to webserver.local:80 via 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., mysql or a GUI like DBeaver) to connect to localhost: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:5432 from your local machine to interact with internal.host:5432.

Useful Options

  • Background Mode: Run the tunnel in the background with -f and -N (no command execution):

    ssh -f -N -L 8080:webserver.local:80 user@ssh.example.com
    
  • Bind 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.com
    
  • Keep 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:3000 becomes accessible on the SSH server at ssh.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:1080 to 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/24 subnet 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 xterm application 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/path directory from the SSH server to /local/mountpoint on your local machine.
  • Unmount: Use umount /local/mountpoint to 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:2222 to access your local machine’s SSH server (localhost:22).

Pro Tips

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=60 to keep the connection alive or consider autossh.

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!