SSH tunneling (port forwarding) lets you securely forward a network port from a remote server to another machine — all traffic is encrypted and no additional software is required beyond a standard SSH client.
SSH tunneling works as a three-part chain. Think of it as routing traffic through a relay — you connect to the middle server, and the middle server transparently forwards your connection to the final destination:
| Part | Role | Example |
|---|---|---|
| Near | Your local machine — initiates the tunnel | your laptop / workstation |
| Middle | An intermediary server you can SSH into — it exposes the forwarded port | 209.239.112.134 |
| Far | The final destination — the server running the service you want to reach | server935 |
The key advantage is that Far does not need to be publicly reachable. As long as Middle can reach Far and you can reach Middle, the tunnel bridges the gap.
The tunnel command uses two important SSH flags:
| Flag | Purpose |
|---|---|
| -N | Do not execute a remote command — keeps the connection open purely for port forwarding without dropping into a shell. |
| -L | Local port forwarding — binds a port on the middle server and forwards traffic to the far server. Format: bind-address/local-port/remote-host/remote-port |
| -f | Optional — runs SSH in the background. Combine with -N to start the tunnel as a background process. |
| -v | Optional — verbose output, useful for debugging connection issues. |
Replace the placeholders with your actual server addresses, IP, and port numbers:
This opens port 110 on the middle server (209.239.112.134) and forwards all connections to port 22 (SSH) on the far server (server935):
Any connection to 209.239.112.134:110 will be transparently forwarded to server935:22 — making the SSH service of the far server reachable via the middle server.
Add the -f flag to send the tunnel to the background so your terminal remains free:
To stop a background tunnel, find its process ID and kill it:
The tunnel stays active as long as the SSH connection is maintained. If the connection drops, you will need to re-run the command to re-establish it. Consider using a tool like autossh for persistent tunnels that reconnect automatically.
| Problem | Likely cause & fix |
|---|---|
| Connection refused on the forwarded port | The middle server's firewall is blocking the port. Open the port in iptables or nftables on the middle server. |
| Tunnel connects but immediately drops | SSH keepalive may not be configured. Add ServerAliveInterval 30 to your ~/.ssh/config. |
| Port forwarding is refused by the server | The middle server may have AllowTcpForwarding no in its /etc/ssh/sshd_config. Set it to yes and restart the SSH service. |
| Binding to the middle server IP fails | By default, SSH only binds to localhost. Set GatewayPorts yes in /etc/ssh/sshd_config on the middle server to allow binding to its public IP. |
For the full reference of all SSH port forwarding options, refer to the official OpenSSH manual.