Local port forwarding (-L)

SSH · Practical · 10 min

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 db forwards your port 5433 to port 5432 on the db server itself (localhost is resolved on the server side). Now psql -h localhost -p 5433 talks to the remote PostgreSQL.
  • ssh -L 8080:internal-api:80 bastion reaches a host that only the bastion can see.

Useful companions:

  • -N runs no remote command (just the tunnel), -f goes to the background after authentication.
  • ExitOnForwardFailure yes makes 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.0 would 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:5432

Remember

  • -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.

Check yourself

  1. In `ssh -L 9000:localhost:80 web`, which machine does `localhost` refer to?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: man.openbsd.org/ssh#L