Tunnels let you reach databases and admin UIs that are deliberately not exposed to the internet.
Local forwarding opens a listening port on your machine and forwards every connection on it, through the SSH connection, to a destination as seen from the server.
The syntax is -L [bind_address:]local_port:destination:destination_port.
ssh -L 5433:localhost:5432 dbforwards your port 5433 to port 5432 on thedbserver itself (localhostis resolved on the server side). Nowpsql -h localhost -p 5433talks to the remote PostgreSQL.ssh -L 8080:internal-api:80 bastionreaches a host that only the bastion can see.
Useful companions:
-Nruns no remote command (just the tunnel),-fgoes to the background after authentication.ExitOnForwardFailure yesmakes ssh exit if the port cannot be bound, instead of connecting without a tunnel.- The listener binds to loopback by default, so only your machine can use it; binding to
0.0.0.0would expose it to your network.
Forwards can live in ~/.ssh/config as LocalForward 5433 localhost:5432. Traffic is encrypted between you and the SSH server; from there to the destination it travels in the clear, so a destination on the server itself (localhost) is the safest pattern.
Example
# expose the remote PostgreSQL on local port 5433
ssh -N -L 5433:localhost:5432 deploy@db.example.com
psql -h localhost -p 5433 -U app shop # in another terminal
# reach a service only visible from the bastion, in the background
ssh -f -N -o ExitOnForwardFailure=yes -L 8080:grafana.internal:3000 bastion
curl -s localhost:8080/api/health
# ~/.ssh/config
# Host db-tunnel
# HostName db.example.com
# LocalForward 5433 localhost:5432Remember
- -L local_port:dest:dest_port, with dest resolved on the server
- -N for tunnel only, -f to background, ExitOnForwardFailure for safety
- Listeners bind to localhost unless you say otherwise
Watch out for
- Reading 'localhost' in -L as your own machine; it is relative to the SSH server.