SSH Port Forwarding
SSH port forwarding (tunneling) is a critical technique for DevOps engineers to securely access internal services, databases, and applications across cloud and hybrid environments (AWS, Azure, GCP). This guide covers local, remote, and dynamic forwarding with actionable examples and best practices.
1. Local Port Forwarding
Forward a local port to a remote service through an SSH server. Useful for accessing internal databases, web UIs, or APIs from your workstation.
Syntax:
ssh -L <local_port>:<destination_host>:<remote_port> <user>@<ssh_server>
Example 1: Forward local port 5050 to remote 4040 via a bastion
ssh -L 5050:188.171.10.8:4040 user@bastion.host
Example 2: Access a private PostgreSQL database
ssh -L 5432:db1.host:5432 user@remote.host
# Connect locally: psql -h 127.0.0.1 -p 5432
Example 3: Forward VNC port and run SSH in background
ssh -L 5901:127.0.0.1:5901 -N -f user@remote.host
-N
: Do not execute remote command-f
: Run SSH in background
Troubleshooting:
Ensure
AllowTcpForwarding yes
is set in/etc/ssh/sshd_config
on the remote server.
2. Remote Port Forwarding
Expose a local service to a remote network via the SSH server. Useful for sharing local apps or webhooks with remote/cloud systems.
Syntax:
ssh -R <remote_port>:localhost:<local_port> <user>@<remote.host>
Example: Expose local port 3000 to remote port 8000
ssh -R 8000:127.0.0.1:3000 -N -f user@remote.host
Now, anyone on
remote.host
can access your local app atlocalhost:8000
.
3. Dynamic Port Forwarding (SOCKS Proxy)
Create a local SOCKS proxy to route traffic through the SSH server. Useful for secure browsing, testing, or accessing internal networks.
Syntax:
ssh -D <local_port> <user>@<ssh_server>
Example: Start a SOCKS proxy on port 9090
ssh -D 9090 -N -f user@remote.host
Configure your browser or CLI tool to use
localhost:9090
as a SOCKS5 proxy.
Real-World DevOps Examples
1. Access AWS RDS or Azure SQL via Bastion
ssh -L 5432:<rds-endpoint>:5432 ec2-user@bastion-host
2. Forward Kubernetes Dashboard securely
ssh -L 8001:localhost:8001 user@k8s-master
kubectl proxy --address='127.0.0.1' --port=8001
3. Share a local web app with a remote team
ssh -R 8080:localhost:3000 user@remote.host
Best Practices
Use
-N -f
for background tunnels in automation scriptsAlways restrict forwarding to trusted users/networks
Monitor and audit SSH tunnels in production
Use SSH config (
~/.ssh/config
) to simplify complex tunnelsFor persistent tunnels, consider tools like
autossh
or systemd services
References
Tip: Kill background SSH tunnels with
pkill -f 'ssh -L'
orpkill ssh
as needed.
Last updated