SSH Tunnels and Port Forwarding
SSH does more than open shells. It can forward TCP ports between machines, creating encrypted tunnels through any network that allows SSH. Three flavors — local, remote, and dynamic — solve very different problems.
Local forwarding (-L) — reach a service THROUGH a server
Maps a local port on YOUR machine to a remote port reachable from the SSH server.
ssh -L 8080:localhost:80 user@server.example.com
Now localhost:8080 on your laptop is connected to server:80 via the encrypted SSH tunnel.
Useful examples
# Reach an internal database not exposed to internet
ssh -L 5432:internal-db:5432 user@bastion.example.com
psql -h localhost -p 5432
# Reach an internal admin panel through a jump host
ssh -L 8443:internal-grafana:443 user@bastion.example.com
# Now visit https://localhost:8443
# Tunnel multiple ports at once
ssh -L 5432:db:5432 -L 6379:redis:6379 user@bastion
Remote forwarding (-R) — expose YOUR local service to the server
Maps a port on the SSH server to a port on YOUR local machine. Useful when the server can’t initiate connections back to you (NAT, firewall) but you want it to reach a service on your laptop.
ssh -R 9000:localhost:3000 user@server.example.com
Now anyone on server who connects to localhost:9000 reaches localhost:3000 on YOUR laptop.
Useful examples
# Quickly demo a local dev server to someone on a remote machine
ssh -R 8080:localhost:3000 user@public-server
# They visit localhost:8080 on the server, see your local site
# Reverse SSH for a machine behind NAT
# Run this on the NAT'd machine to give YOU access:
ssh -R 2222:localhost:22 user@public-server
# Then from anywhere: ssh -p 2222 nat-user@public-server
# → reaches the NAT'd machine
Allowing remote forwards on the server
By default, remote forwards bind only to localhost on the server. To allow other machines to connect:
# In /etc/ssh/sshd_config on the server:
GatewayPorts yes
# Then bind to 0.0.0.0:
ssh -R 0.0.0.0:9000:localhost:3000 user@server
Dynamic forwarding (-D) — SOCKS proxy
Turns SSH into a SOCKS5 proxy. All traffic configured to use it gets tunneled through the SSH connection.
ssh -D 1080 user@server.example.com
Now configure your browser (or any app) to use localhost:1080 as a SOCKS5 proxy. Every connection goes through the server, encrypted and originating from the server’s IP.
Practical use
# Browse the internet through your VPS
ssh -D 1080 user@vps
# Then in Chrome:
chrome --proxy-server="socks5://localhost:1080"
# Or use a browser extension like SwitchyOmega for per-site control
Background tunnels
Most of the time you don’t want an interactive shell along with the tunnel. Use these flags:
ssh -fNL 8080:localhost:80 user@server
# -f go to background after auth
# -N don't execute a remote command (just maintain the tunnel)
# -L the local forward
# -L can be replaced with -R or -D for the other modes
Persistent tunnels with autossh
SSH tunnels die when the connection drops. autossh automatically reconnects.
sudo apt install autossh
autossh -fN -L 8080:localhost:80 user@server
# Run as a systemd service for production reliability
sudo systemctl enable --now myssh-tunnel.service
Config-file tunnels (cleaner)
Define tunnels in ~/.ssh/config so you don’t have to remember commands:
Host db-tunnel
HostName bastion.example.com
User alice
LocalForward 5432 internal-db:5432
LocalForward 6379 internal-redis:6379
# Then just
ssh db-tunnel
Common gotchas
- “Address already in use” — another tunnel or service is on the local port. Pick a different port or kill the conflicting process.
- “Permission denied” on remote forward — remote sshd needs
GatewayPortsenabled to expose the forward beyond localhost. - Tunnel drops — use
ServerAliveInterval 60in your SSH config to keep idle tunnels open through NAT. - Forgetting -N — without it, you also get an interactive shell, which can confuse scripts.
Security considerations
- Tunnels can bypass firewalls — both for legitimate use AND for exfiltration. Some corporate environments forbid SSH tunneling.
- If you forward sensitive services, the LOCAL endpoint is unauthenticated. Anyone on your laptop can connect to the tunneled port.
- Use
ssh-keygen+ key-only auth on the server. Password-protected keys for laptops you carry around.
What to learn next
That covers VPN and tunneling. Next big section: network security — common attacks, segmentation, IDS/IPS, and packet capture. Up next.