SSH Tunneling: Local, Remote and Dynamic Port Forwarding - 夜莺博客

SSH Tunneling: Local, Remote and Dynamic Port Forwarding

SSH tunneling (port forwarding) carries unencrypted or firewalled traffic inside an encrypted SSH connection — reaching an internal database from home, exposing a local dev server to the internet, or turning any SSH server into a SOCKS proxy for private browsing. The three flavors are easy to confuse, so this guide maps local (-L), remote (-R) and dynamic (-D) forwarding to the exact commands, plus the ssh_config shortcuts that keep tunnels reproducible.

Quick Reference

ssh -L 8080:localhost:80 user@server     local forwarding
ssh -R 8080:localhost:3000 user@server    remote forwarding
ssh -D 9090 user@server                   dynamic SOCKS proxy
ssh -L 8080:host1:80 -L 8081:host2:80 user@server   multiple
ssh -J jump.host user@destination         jump host

Local Port Forwarding (-L)

-L binds a port on your machine; the SSH server then connects onward to the destination you name. The destination is resolved from the server's perspective — localhost means the SSH server itself. Reach a database that only listens inside the corporate network:

ssh -L 3336:db001.host:3306 user@pub001.host
mysql -h 127.0.0.1 -P 3336

Remote Port Forwarding (-R)

-R reverses the direction: a port opens on the SSH server and forwards back through the tunnel to your machine. Expose a local web app on a public jump host:

ssh -R 8080:localhost:3000 -N -f user@remote.host

By default the server binds the remote port on loopback only — nothing outside can reach it. Opening it to the world requires GatewayPorts yes (or clientspecified) in the server's /etc/ssh/sshd_config, and an explicit bind address:

ssh -R 0.0.0.0:8080:127.0.0.1:3000 -N -f user@remote.host

Without GatewayPorts the client silently keeps the port on loopback — a classic "it worked in the lab" trap.

Dynamic Port Forwarding (-D): SOCKS Proxy

-D opens a local SOCKS proxy that can reach any destination through the SSH server — no per-service rules needed. Route a browser through it:

ssh -D 9090 -N -f user@remote.host

Point the browser or application at SOCKS5 127.0.0.1:9090 and all its traffic rides the tunnel to the server before going out.

Useful Options

  • -N — no remote command; pure tunnel.
  • -f — background after authentication.
  • -o ExitOnForwardFailure=yes — fail visibly if the bind fails.
  • -o ServerAliveInterval=60 — keep long-lived tunnels from being reaped.
  • -p — non-default SSH port.

ssh_config Aliases for Tunnels

Host tunnel-db
    HostName pub001.host
    User user
    LocalForward 3336 db001.host:3306

Host tunnel-socks
    HostName remote.host
    User user
    DynamicForward 9090
ssh -N tunnel-db

Troubleshooting

  • channel 2: open failed: connect failed: Connection refused — the tunnel is up but the destination service is unreachable from the SSH server; test from that server.
  • Remote port unreachable from outside — check GatewayPorts and the server firewall.
  • Tunnel drops after idle — add ServerAliveInterval; for production reverse tunnels wrap the command with autossh/systemd.

SSH tunnels are the network engineer's swiss knife — combine them with ss/netstat/tcpdump to validate what the tunnel actually carries, and see Juniper SRX IPsec VPN for the device-level alternative.

原文链接:https://linuxize.com/post/how-to-setup-ssh-tunneling