Kennisbank › Vpn Tunnels › ssh tunnel
vpn tunnels starter 27 August 2026

ssh tunnel

SSH Tunneling: Port Forwarding under the hood

The technical basis is in RFC 4254, The Secure Shell (SSH) Connection Protocol, published on January 6, 2006. This RFC defines how SSH multiplexes one authenticated transport connection into multiple logical channels. One of these is TCP/IP forwarding — port forwarding. A single SSH connection can thus securely forward multiple network services at once.

The terms port forwarding and tunneling are used as synonyms in technical documentation. The Apache MINA SSHD documentation states explicitly that TCP/IP port forwarding is the same as tunneling: proxying a TCP/IP connection via an SSH channel. The transport layer itself is described in RFC 4253, The Secure Shell (SSH) Transport Layer Protocol, also published on January 6, 2006. RFC 4253 covers key exchange and authentication. Only then does the connection layer become available, in which port forwarding is defined.

Steps: Local Port Forwarding

Local port forwarding is the most commonly used form. You link a local port on your own machine to a port on an external server, via an SSH connection. Red Hat documents the command as:

ssh -L local-port:remote-hostname:remote-port user@hostname

Step 1: Determine the tunnel parameters

Choose a local port that is free on your machine. Choose the remote-hostname and remote-port of the service you want to reach, as seen from the SSH server. For a web server on the SSH server itself, use `localhost` as the remote-hostname and `80` as the remote-port.

Step 2: Open the tunnel

ssh -L 8080:localhost:80 user@192.168.1.10

The SSH client now listens on local port 8080. Each connection to that port is sent encrypted to the SSH server. From the server, the traffic is forwarded to `localhost:80` — the web server on the SSH server itself. The SSH server remains active in the foreground; you see the shell prompt of the server.

Step 3: Make a connection through the tunnel

Open a second terminal on your local machine and type:

curl http://localhost:8080

You get the HTTP response from the web server on the SSH server, without port 80 on the server needing to be externally reachable.

Steps: Reverse Port Forwarding

Reverse port forwarding is used when an external party needs access to a service on your local machine, while you are behind a firewall or NAT. The `-R` option forwards a port on the SSH server to a port on the client.

Step 4: Start reverse forwarding

ssh -R 9000:localhost:3000 user@192.168.1.10

The SSH server now listens on port 9000. Traffic that arrives there travels through the SSH tunnel to your local machine and comes out on `localhost:3000` — for example, a local development server. This is often used for on-site support or debugging applications on a local development platform.

Step 5: Test the reverse tunnel from the server

curl http://localhost:9000

Run this in an SSH session on the server itself. You get the response from the service on your local machine.

Steps: Dynamic Port Forwarding

Dynamic port forwarding creates a SOCKS proxy on the local machine. Unlike fixed forwarding, where you specify a specific host and port, dynamic forwarding sends each connection that comes through the SOCKS port through the SSH tunnel. The destination is determined by the client itself.

Step 6: Start dynamic forwarding

ssh -D 1080 user@192.168.1.10

The SSH client now runs a SOCKS5 proxy on local port 1080. You can set this proxy in a browser, or use it with tools like `curl`:

curl --socks5-hostname localhost:1080 http://example.com

This technique is useful for secure browsing via an external server or for reaching multiple internal services without setting up port forwarding in advance.

Configuration and Limitations

The SSH client reads its configuration from `ssh_config`; the server from `sshd_config`. By default, port forwarding is allowed. Administrators can restrict or disable it to prevent tunneling to internal services.

The most important server option is `AllowTcpForwarding`. If you set this to `no`, the server refuses all forwarding requests:

<h2>/etc/ssh/sshd_config</h2>
AllowTcpForwarding no

After a change, restart the SSH daemon:

sudo systemctl restart sshd

The `sshd` daemon listens on port 22 by default and starts automatically at system boot, via systemd or `/etc/init.d/ssh`.

Verification

Check whether the tunnel is active with:

ss -tlnp | grep -E '8080|9000|1080'

This shows the listening ports on your local system. For a more detailed check of the SSH connection itself:

ssh -v -L 8080:localhost:80 user@192.168.1.10

The `-v` flag shows detailed debug output, including the establishment of the tunnel.

Frequently asked problems

1. "bind: Address already in use"

The local port is already in use. Choose a different port or close the process that uses the port:

sudo lsof -i :8080

2. "channel 0: open failed: connect failed"

The SSH server cannot reach the remote hostname or remote port. Check that the service is running on the server and that the remote hostname is correct as seen from the server. Use `localhost` if the service runs on the SSH server itself.

3. "Permission denied (publickey)"

The server does not accept password authentication. Use SSH keys instead of passwords — this also increases the security of your tunnels. Generate a key pair:

ssh-keygen -t ed25519
ssh-copy-id user@192.168.1.10

Security considerations

A misconfigured tunnel can unintentionally expose internal services. Manage the settings in `sshd_config` carefully. Use SSH keys instead of passwords for authentication. Consider setting `AllowTcpForwarding` explicitly, even if you want to allow forwarding — the default can vary by distribution.

The SSH standard is the result of collective development within the internet community. The specifications include RFC 4250 through RFC 4256, which together form the official basis for modern SSH implementations such as OpenSSH. An exact inventor or place of origin is not documented; the current standard has grown through years of contributions from various authors and organizations.

The three forms of forwarding — local, reverse, and dynamic — cover most practical scenarios. Local forwarding for reaching internal services, reverse forwarding for exposing local services to the outside, and dynamic forwarding for flexible SOCKS proxy access. Which form you choose depends on the direction in which traffic needs to flow and whether the destination is known in advance.

The power of SSH tunneling lies in its simplicity: you need no extra software, only a working SSH connection. But that simplicity also tempts carelessness — a tunnel you no longer use should be closed. A forgotten reverse tunnel can expose a development environment to the entire network of the server. Control over your tunnels is just as important as the ability to open them.

← Back to knowledge base
← Terug naar kennisbank