SSH Port Forwarding and Tunneling
SSH is well known as the protocol that brings a remote server right to your fingertips. The services it provides can be grouped into three categories: command execution, file transfer, and tunneling.
Tunneling is one of SSH’s lesser known capabilities. It allows bidirectional network traffic between your local machine and a remote server, creating an encrypted pathway through untrusted networks.
Local Port Forwarding
Local port forwarding makes a port on your machine behave as if it is a port on the remote server, or on another machine the server can reach. The syntax is:
ssh user@server -L <local-port>:<remote-address>:<remote-port>A common scenario: your application server runs MySQL on localhost:3306, but the database port is not exposed to the outside world. You can forward a local port through SSH to reach it:
ssh user@server -L 3307:localhost:3306Now point your local database client to localhost:3307. Traffic to that port travels through the encrypted SSH tunnel to the server and reaches MySQL on localhost:3306.
The remote address does not have to be the server itself. You can forward to any host the server can reach on its network. For example, if the database runs on a separate machine at 10.20.30.40:
ssh user@server -L 3307:10.20.30.40:3306The SSH server acts as a relay. Your local traffic is forwarded to the server, which then connects to 10.20.30.40:3306 on your behalf.
Remote Port Forwarding
Remote port forwarding is the reverse direction. It shares a port from your local machine (or a machine on your local network) with the remote server.
ssh user@server -R <remote-port>:<local-address>:<local-port>Suppose you are working on a machine behind NAT and want to expose your local SSH server to the internet. You have access to a public server that you can SSH into. Use remote forwarding:
ssh user@server -R 2222:localhost:22This makes port 2222 on the server forward traffic to your local machine’s port 22. Anyone who can reach the server can now connect to your local machine:
ssh user@server -p 2222This technique is useful for accessing development environments behind firewalls, sharing local services with colleagues, or maintaining access to machines that do not have a public IP.
Dynamic Port Forwarding (SOCKS Proxy)
Dynamic port forwarding creates a SOCKS proxy on your local machine. Instead of forwarding a single port, it allows any application that supports SOCKS to route traffic through the SSH server.
ssh user@server -D 8888Once the tunnel is established, configure your applications or system to use the SOCKS proxy:
export HTTP_PROXY=socks5://localhost:8888
export HTTPS_PROXY=socks5://localhost:8888All your HTTP and HTTPS traffic is now routed through the remote server. This works like a poor man’s VPN: your traffic exits from the server’s network, your IP is masked, and the connection is encrypted between your machine and the server.
Browsers, download managers, and most CLI tools that respect proxy environment variables work seamlessly with this setup.
Useful Flags
Two flags make SSH tunnels more practical:
| Flag | Function |
|---|---|
-N | Do not execute a remote command. Useful when all you want is the tunnel, not a shell session. |
-f | Fork SSH into the background after authentication. The tunnel runs as a daemon. |
Combine them for a clean background tunnel:
ssh user@server -L 3307:localhost:3306 -N -fRelated Tools
SSH tunneling is powerful, but it is not always the most convenient solution. Several tools build on or replace SSH tunneling for specific use cases:
sshuttle acts as a transparent proxy that forwards all TCP traffic over SSH. It does not require per-application proxy configuration. Once running, it works like a full VPN tunnel over SSH without requiring administrative privileges on the server.
chisel creates TCP and UDP tunnels over a single HTTP connection. It is useful when firewalls block SSH but allow HTTP. Chisel bundles its own client and server in a single binary and works well in restrictive network environments.
iodine tunnels IPv4 traffic over DNS queries. When a network only allows DNS traffic (captive portals, airport Wi-Fi, hotel networks), iodine encodes your data in DNS requests and responses. It achieves much higher bandwidth than similar DNS tunneling tools.
Wrapping Up
SSH port forwarding and tunneling turn a simple remote access protocol into a versatile networking tool. Local forwarding brings remote services to your machine. Remote forwarding exposes your local services to remote networks. Dynamic forwarding creates a full SOCKS proxy for all your traffic.
These techniques solve problems that come up daily: accessing databases behind firewalls, exposing development servers, and securing traffic on untrusted networks. The extra flags and related tools extend SSH’s capabilities even further.
Mastering these three forwarding modes gives you a reliable networking Swiss army knife that works in almost any environment.
You can read this post in Turkish.
Originally published in Turkish on Medium.