SSH Tunneling

SSH tunneling validation guide

SSH forwarding is an administrative feature that can cross network trust boundaries. Use it only for endpoints and services named in authorization. Bind to loopback by default, use the narrowest destination, preserve host-key checking, and keep an operator-visible session unless the runbook requires background operation.

Forwarding model

Mode Listener Connection made by Typical authorized use
Local -L SSH client SSH server reach one internal service through a bastion
Remote -R SSH server SSH client expose one local lab service to the SSH server
Dynamic -D SSH client SSH server SOCKS access through a managed bastion

Local forwarding

The SSH client listens on loopback and asks the SSH server to connect to one destination:

ssh -N -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:15432:db.internal.example:5432 \
  operator@approved-bastion.example

Validate with one benign database health query or TCP connection. The destination name is resolved and reached from the SSH server's network position.

For a second SSH hop, prefer the standard jump-host feature:

ssh -J operator@approved-bastion.example admin@approved-private-host.example

Remote forwarding

Keep the remote listener on the SSH server's loopback interface unless a reviewed requirement says otherwise:

ssh -N -o ExitOnForwardFailure=yes \
  -R 127.0.0.1:18080:127.0.0.1:8080 \
  operator@approved-gateway.example

A process on the gateway can now reach the approved local lab service at 127.0.0.1:18080. Do not set GatewayPorts yes for a single test. If another approved host must connect, use a dedicated bastion configuration with GatewayPorts clientspecified, host firewall restrictions, and an exact source allowlist. Back up the configuration, validate it with sshd -t, and restore it during cleanup.

Dynamic forwarding

Use a loopback SOCKS listener and direct only approved applications through it:

ssh -N -o ExitOnForwardFailure=yes \
  -D 127.0.0.1:1080 operator@approved-bastion.example

Confirm whether the client resolves DNS locally or through the proxy. Validate one approved host and port; do not use a broad subnet scan as a tunnel test.

Server controls

A managed bastion can restrict forwarding in sshd_config or authorized_keys:

AllowTcpForwarding local
PermitOpen db.internal.example:5432

PermitOpen accepts host and port destinations, not CIDR ranges. Pair it with account restrictions, MFA or short-lived certificates, firewall policy, and session logging.

Verification and cleanup

# Client-side listeners
lsof -nP -iTCP -sTCP:LISTEN

# Stop the foreground SSH session with Ctrl-C, then confirm the listener closed.

Record the SSH client and server, source and destination, listener address, ports, start and end time, one benign validation request, and relevant authentication, process, and network events. Remove temporary server configuration and firewall rules and confirm the original state.

References