SSH Cheatsheet

Port Forwarding and Tunneling

Use this SSH reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Tunnel Types at a Glance

TypeFlagDirectionUse case
Local forwarding-LLocal port → Remote serviceAccess a remote DB locally
Remote forwarding-RRemote port → Local serviceExpose local service through server
Dynamic (SOCKS)-DLocal SOCKS proxy → anywhereRoute browser traffic via SSH host

Local Port Forwarding (-L)

ssh -L [local_addr:]local_port:dest_host:dest_port user@gateway

Traffic to localhost:local_port on your machine is forwarded through gateway to dest_host:dest_port (as seen from gateway).

# Access a remote MySQL (port 3306) locally on port 3307
ssh -L 3307:localhost:3306 user@dbserver
mysql -h 127.0.0.1 -P 3307 -u root -p

# Access an internal service through a bastion
ssh -L 8080:internal-app.private:80 user@bastion

# Bind to a specific local address (share with LAN)
ssh -L 0.0.0.0:8080:internal:80 user@bastion

# Background tunnel (no shell)
ssh -fNL 5432:db.internal:5432 user@bastion

Remote Port Forwarding (-R)

ssh -R [remote_addr:]remote_port:dest_host:dest_port user@gateway

Traffic arriving at remote_port on gateway is forwarded back to dest_host:dest_port on your side.

# Expose local dev server (port 3000) on remote port 8080
ssh -R 8080:localhost:3000 user@public-server

# Let others on the remote server reach your local port
# (requires GatewayPorts yes in /etc/ssh/sshd_config on the server)
ssh -R 0.0.0.0:8080:localhost:3000 user@public-server

# Background
ssh -fNR 9000:localhost:9000 user@public-server

Dynamic (SOCKS5) Proxy (-D)

ssh -D [bind_addr:]local_port user@gateway

Opens a SOCKS5 proxy on local_port. Configure your browser/app to use 127.0.0.1:PORT as SOCKS5 proxy.

# SOCKS5 proxy on localhost:1080
ssh -D 1080 user@gateway

# Background
ssh -fND 1080 user@gateway

# Test: curl through the proxy
curl --socks5 127.0.0.1:1080 https://example.com

Flags for Tunnel-Only Connections

FlagEffect
-NDon't run a remote command (no shell)
-fFork to background after authenticating
-qQuiet — suppress banners
# Canonical background tunnel invocation
ssh -fNq -L 5432:db:5432 user@bastion

Config File Tunnels

Persistent tunnels belong in ~/.ssh/config, but OpenSSH doesn't auto-restart them. Use autossh for that.

Host db-tunnel
    HostName bastion.example.com
    User ubuntu
    LocalForward 5432 db.internal:5432
    LocalForward 6379 redis.internal:6379
    ServerAliveInterval 30
    ExitOnForwardFailure yes
ssh -fNq db-tunnel

autossh — Auto-Restart Tunnels

# Install
brew install autossh    # macOS
apt install autossh     # Debian/Ubuntu

# Persistent local forward
autossh -M 0 -fNq -L 5432:db:5432 user@bastion

-M 0 disables the monitoring port (use ServerAliveInterval instead).

Checking Active Tunnels

# List listening ports
ss -tlnp | grep ssh      # Linux
lsof -iTCP -sTCP:LISTEN | grep ssh   # macOS

# Close a named tunnel via control socket
ssh -S ~/.ssh/cm-user@bastion -O cancel -L 5432:db:5432 user@bastion

X11 Forwarding

Forwards a remote GUI application to your local display.

ssh -X user@host xclock       # basic (untrusted)
ssh -Y user@host xclock       # trusted (needed for some apps)

Server must have X11Forwarding yes in /etc/ssh/sshd_config.