Home/Engineer/Networking / Servers/SSH Port Forwarding: Reachin…
Networking / ServersIntermediateUbuntuDebianCentOSmacOSsshsocksbastion

SSH Port Forwarding: Reaching Private Databases with -L, Exposing Internal Services with -R, and SOCKS Proxies with -D

How to reach databases and Redis with local port forwarding, expose an internal server with remote port forwarding, and set up a SOCKS proxy with dynamic port forwarding.

Contents
  1. Three Types of Port Forwarding
  2. Local Port Forwarding (-L)
  3. Remote Port Forwarding (-R)
  4. Dynamic Port Forwarding (-D) — SOCKS Proxy
  5. Automating Tunnels with ~/.ssh/config
  6. Managing Tunnel Processes

Three Types of Port Forwarding

TypeFlagUse case
Local-LLocal port → access a remote service
Remote-RRemote port → expose a local service
Dynamic-DSOCKS proxy (tunnel all traffic)

Local Port Forwarding (-L)

Pattern: a port on your machine → via the server → a service on the server side

Bash
# Syntax
ssh -L [local_ip:]local_port:destination_host:destination_port server

# Connect to PostgreSQL on the server from your local machine
ssh -L 15432:localhost:5432 deploy@prod-server.example.com
# Then locally: psql -h localhost -p 15432 -U admin

# Access Redis behind a firewall
ssh -L 16379:10.0.1.5:6379 deploy@bastion.example.com
# redis-cli -h localhost -p 16379

# Multiple ports at once
ssh -L 15432:localhost:5432     -L 16379:localhost:6379     -L 18080:localhost:8080     deploy@prod-server.example.com

# Keep the tunnel without a shell (-N)
ssh -N -L 15432:localhost:5432 deploy@prod-server.example.com

# Run in the background (-f -N)
ssh -f -N -L 15432:localhost:5432 deploy@prod-server.example.com

Remote Port Forwarding (-R)

Pattern: a port on the server → expose a local service (publish a local server behind NAT to the outside)

Bash
# Syntax
ssh -R [remote_ip:]remote_port:destination_host:destination_port server

# Expose local port 3000 as port 8080 on the server
ssh -R 8080:localhost:3000 user@public-server.example.com
# Now public-server.example.com:8080 reaches localhost:3000 on your machine

# Required on the server in /etc/ssh/sshd_config
# GatewayPorts yes    # Allow the remote port to be reached from outside

Dynamic Port Forwarding (-D) — SOCKS Proxy

Pattern: turn a local port into a SOCKS5 proxy — send all traffic through the server

Bash
# Start a SOCKS5 proxy (local port 1080)
ssh -D 1080 user@server.example.com

# Or in the background
ssh -f -N -D 1080 user@server.example.com

# Use the SOCKS5 proxy with curl
curl --socks5 localhost:1080 https://example.com

# Browser settings:
# Firefox → Settings → Network → SOCKS5 proxy localhost:1080

Automating Tunnels with ~/.ssh/config

CODE
# Open DB tunnels automatically on connect
Host prod-with-tunnel
    HostName prod-server.example.com
    User deploy
    LocalForward 15432 localhost:5432
    LocalForward 16379 localhost:6379

# Tunnel via a jump host
Host internal-via-bastion
    HostName 10.0.1.50
    User ubuntu
    ProxyJump bastion
    LocalForward 18080 localhost:8080
Bash
# After configuring, connect and open tunnels in one step
ssh prod-with-tunnel

Managing Tunnel Processes

Bash
# List running SSH tunnels
ps aux | grep "ssh -"
# Or
ss -tlnp | grep ssh

# Stop the tunnel on a specific port
pkill -f "ssh -N -L 15432"

# Auto-reconnect tunnels with autossh
sudo apt install -y autossh
autossh -M 0 -f -N -L 15432:localhost:5432 deploy@prod-server.example.com
#ssh#socks#bastion
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)Redis documentation ↗Linux man pages ↗

Questions & answers

Ask a question about this guide. We'll review and reply.