SSH tunnels allow secure access to remote services through encrypted connections. They leverage existing SSH infrastructure, require no extra software, and can expose services that are otherwise only accessible from internal networks. They practically replace VPNs for simple scenarios like accessing databases, web applications, or admin interfaces behind a firewall.
Local forwarding¶
ssh -L 5433:localhost:5432 user@db-server
ssh -L 8080:internal-app:80 user@bastion
Local forwarding opens a port on your local machine and routes traffic through SSH to the target server. The first example makes PostgreSQL on the db-server available as localhost:5433. The second example exposes an internal application through a bastion host. The advantage is that the target service does not need to be reachable from the internet — it only needs to be accessible from the SSH server.
Remote forwarding¶
ssh -R 8080:localhost:3000 user@public-server
Remote forwarding works in reverse — it exposes a local service through a remote server. Typical use case: you have a development server behind NAT and want to temporarily share it with a colleague via a public server. Port 3000 on your machine becomes available as port 8080 on the public server.
Dynamic (SOCKS)¶
ssh -D 1080 user@ssh-server
curl --socks5 localhost:1080 http://internal.local
Dynamic forwarding creates a SOCKS proxy through which any traffic can be routed. A browser or application configured to use SOCKS proxy localhost:1080 will access the network from the SSH server’s perspective. Useful for accessing an entire internal network without creating a separate tunnel for each service.
Jump host¶
ssh -J bastion user@internal-server
# ~/.ssh/config
Host internal-\*
ProxyJump bastion
A jump host (bastion) acts as an intermediary for accessing internal networks. SSH config with ProxyJump enables transparent connections through the bastion — just ssh internal-server and SSH automatically routes through the bastion.
Persistent Tunnels¶
autossh -M 0 -f -N -L 5433:localhost:5432 user@db-server
For production use, autossh is essential — it automatically restarts the tunnel when the connection drops. Alternatively, create a systemd service unit for a persistent tunnel with automatic restart and logging.
SSH Tunnels = Secure Access¶
For simple scenarios, SSH tunnels replace VPNs. For more complex topologies or team-wide access, consider WireGuard or Tailscale.