SSH Proxy by

Local Port Forward ssh -L

Forward a port on your local machine to a remote host through the SSH server. Use case: access a database or web service behind a firewall.

Local Bind Local Port Remote Host Remote Port

Command

Remote Port Forward ssh -R

Expose a local service to the remote server. Use case: let a remote server access your local dev environment, webhook testing.

Remote Bind Remote Port Local Host Local Port

Command

Dynamic / SOCKS Proxy ssh -D

Create a SOCKS5 proxy tunnel. All traffic routed through this proxy exits at the SSH server. Use case: bypass firewalls, route Android Studio / browser traffic through a remote server.

After starting the tunnel, configure your applications to use the SOCKS5 proxy. Use the Proxy Settings generator to create the configuration commands.

Command

Jump Host / Multi-Hop ssh -J

Connect to a destination through one or more intermediate jump hosts (bastion servers). Modern -J flag (OpenSSH 7.3+) or legacy ProxyCommand.

# Host Port User
1

Command

SSH Config ~/.ssh/config

Generate SSH config entries for ~/.ssh/config. Define hosts with forwarding rules, keep-alive settings and proxy jumps.

Type Bind:Port Target:Port

~/.ssh/config

Proxy Settings

Generate proxy configuration commands for your shell, OS settings and applications. Typically used after setting up a SOCKS tunnel with ssh -D.

Shell & System
Dev Tools
Package Managers
Cloud CLIs

Configuration Commands

Management Script

Generate a production-ready start/stop/status/restart script for managing SSH tunnels. Well-commented for beginners.

Name Type SSH Host User Port Forward Key opt.

Script

Autostart Setup

Generate OS-specific autostart configuration to run your SSH tunnels at boot. Includes the management script and the service/launch config.

Output

Troubleshooting Guide

The SSH client could not connect to the server on the specified port. Common causes: SSH daemon not running, wrong port, firewall blocking.

Diagnostic Commands
Solutions
  • Verify the SSH server is running: systemctl status sshd
  • Check the correct port in /etc/ssh/sshd_config (look for Port)
  • Check firewall rules allow incoming connections on the SSH port
  • Try connecting with verbose output: ssh -vvv user@host

The server rejected all offered authentication methods. Usually means the key is not in ~/.ssh/authorized_keys or file permissions are wrong.

Diagnostic Commands
Solutions
  • Check key permissions: chmod 600 ~/.ssh/id_ed25519 and chmod 700 ~/.ssh
  • Verify your public key is in ~/.ssh/authorized_keys on the server
  • Check /etc/ssh/sshd_config for PubkeyAuthentication yes
  • Check SELinux context: restorecon -Rv ~/.ssh (RHEL/CentOS)

The local port you want to forward is already bound by another process. SSH will fail to bind with bind: Address already in use.

Diagnostic Commands
Solutions
  • Kill the process occupying the port
  • Choose a different local port for the tunnel
  • Use -o ExitOnForwardFailure=yes to fail cleanly instead of silently ignoring

The server's host key doesn't match the stored fingerprint in ~/.ssh/known_hosts. This can indicate a server reinstall or a man-in-the-middle attack.

Diagnostic Commands
Solutions
  • If the server was reinstalled, remove the old key: ssh-keygen -R hostname
  • Verify the new fingerprint with the server admin before accepting
  • Warning: Do not blindly add StrictHostKeyChecking no in production

The SSH connection was dropped unexpectedly. Common with idle tunnels, NAT timeouts, or unstable networks.

Diagnostic Commands
Solutions
  • Add KeepAlive: -o ServerAliveInterval=60 -o ServerAliveCountMax=3
  • Use TCPKeepAlive yes in SSH config
  • Use the Management Script generator to create auto-reconnect logic
  • Check if a firewall or NAT gateway is timing out idle connections

The SSH server rejected the forwarding request. This happens when AllowTcpForwarding is disabled or the target host:port is unreachable from the server.

Diagnostic Commands
Solutions
  • Check /etc/ssh/sshd_config for AllowTcpForwarding yes
  • For remote forwards, check GatewayPorts setting
  • Verify the target host:port is reachable from the SSH server
  • Check if per-user restrictions apply in Match blocks

The SSH SOCKS tunnel is running but applications don't route traffic through it. Usually a configuration issue.

Diagnostic Commands
Solutions
  • Verify the tunnel is running: ss -tlnp | grep 1080
  • Test with curl: curl --socks5 127.0.0.1:1080 https://ifconfig.me
  • Make sure the app supports SOCKS5 (not just HTTP proxy)
  • Check NO_PROXY / no_proxy env vars aren't excluding your target
  • Use the Proxy Settings generator to configure applications correctly

autossh is a separate program (not part of OpenSSH) that monitors an SSH connection and automatically restarts it when it drops. It is the standard tool for persistent SSH tunnels.

Installation
How it works
  • autossh wraps the ssh command and monitors the connection
  • When the connection drops, autossh automatically reconnects
  • Use -M 0 to disable the legacy monitoring port and rely on ServerAliveInterval / ServerAliveCountMax instead (recommended)
  • AUTOSSH_GATETIME=0 starts monitoring immediately (useful for tunnels started at boot)
Example
autossh -M 0 -N -f -L 3306:127.0.0.1:3306 -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@server.example.com
Alternatives (no extra installation)
  • while loop: while true; do ssh -N -L ...; sleep 5; done — simple but no health checks
  • systemd: Use Restart=always in a service unit (see Autostart Setup generator)
  • Management Script: Use the Management Script generator with auto-reconnect enabled

Tip: The Local Forward, Remote Forward and Dynamic/SOCKS generators all have an Auto-Reconnect checkbox that generates ready-to-use autossh or while-loop commands.

The SSH agent is not running, not accessible, or your key is not loaded. Common when using multiple terminals, tmux/screen, cron jobs, or after reboot.

Diagnostic Commands
Solutions
  • Start the agent: eval "$(ssh-agent -s)"
  • Add your key: ssh-add ~/.ssh/id_ed25519
  • Persist across sessions: add AddKeysToAgent yes to ~/.ssh/config
  • For tmux/screen: use a fixed SSH_AUTH_SOCK path or symlink
  • macOS Keychain: ssh-add --apple-use-keychain ~/.ssh/id_ed25519
  • systemd user service: systemctl --user enable --now ssh-agent

When using a SOCKS5 proxy, DNS queries may still leak to your local resolver instead of being resolved through the tunnel. This defeats privacy and can cause failures when accessing internal hostnames.

Diagnostic Commands
Solutions
  • Use curl --socks5-hostname (not --socks5) to resolve DNS through the proxy
  • Firefox: set network.proxy.socks_remote_dns = true in about:config
  • Chrome: launch with --proxy-server="socks5://127.0.0.1:1080" --host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE 127.0.0.1"
  • Use proxychains with proxy_dns enabled for arbitrary applications
  • Key difference: --socks5 resolves DNS locally, --socks5-hostname sends the hostname to the SOCKS server for resolution

SSH tunnels break when switching networks (Wi-Fi to mobile, VPN connect/disconnect, laptop sleep/wake). The TCP connection becomes stale but SSH may not detect it immediately.

Diagnostic Commands
Solutions
  • Use aggressive keepalive: ServerAliveInterval 15 + ServerAliveCountMax 3 (detects dead connection in 45s)
  • Use autossh for automatic reconnection (see Autostart generator above)
  • Use mosh instead of SSH for interactive sessions (roaming-friendly, UDP-based)
  • systemd service with Restart=always and RestartSec=5
  • Combine TCPKeepAlive yes with ServerAliveInterval for dual detection
  • NetworkManager dispatcher: restart tunnels on network change with /etc/NetworkManager/dispatcher.d/ scripts
  • macOS: use launchd with WatchPaths on network change plist events

Port Forwarding Types

TypeFlagDirectionUse CaseSyntax
Local -L Local → Remote Access remote service via local port -L [bind:]port:host:hostport
Remote -R Remote → Local Expose local service to remote server -R [bind:]port:host:hostport
Dynamic -D SOCKS5 Proxy Route all traffic through SSH server -D [bind:]port
Jump -J Multi-hop Connect through bastion/jump hosts -J user@jump1,user@jump2

Local Forward (-L)

You (localhost:8080) | | SSH encrypted tunnel v SSH Server (server.example.com) | | Plain connection v Target (db.internal:3306)

Traffic to localhost:8080 is tunneled to db.internal:3306 via the SSH server.

Remote Forward (-R)

External Client | | Connects to server:8080 v SSH Server (server.example.com:8080) | | SSH encrypted tunnel (reverse) v You (localhost:3000)

Traffic to server:8080 is tunneled back to your localhost:3000.

Dynamic / SOCKS (-D)

App (browser, curl, etc.) | | SOCKS5 to localhost:1080 v SSH Client (SOCKS proxy) | | SSH encrypted tunnel v SSH Server → Internet (all traffic exits here)

All traffic routed through the SOCKS proxy exits at the SSH server, like a lightweight VPN.

Jump Host (-J)

You (workstation) | | SSH to bastion (hop 1) v Bastion (jump.example.com) | | SSH to target (hop 2) v Target (internal.example.com)

Multi-hop connection through one or more intermediate hosts. No agent forwarding needed with -J.

Common SSH Flags

FlagDescription
-LLocal port forwarding
-RRemote port forwarding
-DDynamic SOCKS proxy
-JJump host (ProxyJump, OpenSSH 7.3+)
-NDon't execute remote command (tunnel only)
-fGo to background after authentication
-CEnable compression
-iIdentity file (private key)
-pSSH port (if not 22)
-oSet SSH option (e.g. -o ServerAliveInterval=60)
-v / -vv / -vvvVerbose output (more v's = more detail)
-gAllow remote hosts to connect to local forwarded ports
-TDisable pseudo-terminal allocation
-qQuiet mode (suppress warnings)

Do

  • Use Ed25519 or RSA 4096-bit keys
  • Set ExitOnForwardFailure yes
  • Bind to 127.0.0.1 unless external access is needed
  • Use ServerAliveInterval to detect broken connections
  • Use -J (ProxyJump) instead of agent forwarding through bastions
  • Set specific AllowTcpForwarding per user in sshd_config
  • Use separate keys for different purposes/servers
  • Rotate keys regularly

Don't

  • Bind to 0.0.0.0 unless you need external access
  • Use StrictHostKeyChecking no in production
  • Forward agent (-A) through untrusted hosts
  • Use password authentication for automated tunnels
  • Run SSH tunnels as root unnecessarily
  • Ignore host key changes without verifying the cause
  • Use PermitRootLogin yes on jump hosts
  • Leave unused forwards open

Example Scenarios

Access Remote Database
ssh -L 3306:127.0.0.1:3306 -N -f user@server.com

Connect to MySQL on localhost:3306 as if it were running locally.

Expose Local Dev Server
ssh -R 80:127.0.0.1:3000 -N -f user@public-server.com

Make your local dev server accessible at public-server.com:80.

SOCKS5 Tunnel through Firewall
ssh -D 1080 -N -f -C user@external-server.com

Route browser/app traffic through an external server to bypass restrictive firewalls.

Multi-Hop to Internal Server
ssh -J jumpuser@bastion.com admin@internal.server

Connect to an internal server through a bastion host in one command.

SSH Key Generation Best Practices

Recommended: Ed25519
ssh-keygen -t ed25519 -C "user@example.com"
  • Fastest, smallest keys (256-bit)
  • Strong security (EdDSA / Curve25519)
  • Supported in OpenSSH 6.5+ (2014)
  • Not supported by very old systems or some hardware tokens
Alternative: RSA 4096-bit
ssh-keygen -t rsa -b 4096 -C "user@example.com"
  • Universal compatibility (all SSH implementations)
  • Larger keys, slower operations
  • Minimum 3072 bits recommended (NIST)
  • Use when Ed25519 is not supported
AlgorithmKey SizeSecuritySpeedCompatibility
Ed25519256 bitExcellentFastestOpenSSH 6.5+
RSA4096 bitGoodSlowerUniversal
ECDSA256/384/521 bitGoodFastOpenSSH 5.7+
DSA1024 bitDeprecatedSlowLegacy only
Useful Commands
# Generate key with custom path
ssh-keygen -t ed25519 -f ~/.ssh/project_key -C "project@example.com"

# Change passphrase on existing key
ssh-keygen -p -f ~/.ssh/id_ed25519

# Show key fingerprint
ssh-keygen -l -f ~/.ssh/id_ed25519.pub

# Copy public key to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

# Convert OpenSSH to PEM format
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa

Tip: Always protect your private key with a passphrase. Set correct permissions: chmod 700 ~/.ssh and chmod 600 ~/.ssh/id_*.

Connection Multiplexing (ControlMaster)

SSH multiplexing allows multiple sessions to share a single TCP connection to the same host. The first connection becomes the "master", and subsequent connections reuse it — eliminating the overhead of TCP handshake, key exchange, and authentication.

Configuration
# ~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 600
  • ControlMaster auto — automatically use or create a master connection
  • ControlPath — socket file location (%r=user, %h=host, %p=port)
  • ControlPersist 600 — keep master alive 600s after last session closes
Management Commands
# Check master status
ssh -O check user@host

# Terminate master connection
ssh -O exit user@host

# Forward new port through existing master
ssh -O forward -L 8080:localhost:80 user@host

# Cancel a specific forward
ssh -O cancel -L 8080:localhost:80 user@host

Create the socket directory first: mkdir -p ~/.ssh/sockets && chmod 700 ~/.ssh/sockets

Performance: Multiplexing can reduce connection time from ~1s to ~0.05s. Particularly useful with Ansible, rsync, git, or scripts that open many SSH connections in sequence.

SSH Tunnels vs Alternatives

ToolTypeBest ForProsCons
SSH Tunnels Port forwarding / SOCKS Quick access to internal services No extra software, encrypted, everywhere TCP only, single-host, manual management
WireGuard VPN (Layer 3) Full network access, always-on VPN Fast, low overhead, kernel-level, UDP Requires setup on both ends, root access
ngrok / Cloudflare Tunnel Reverse tunnel SaaS Exposing local services, demos, webhooks No server needed, HTTPS/domains, easy setup Third-party dependency, free tier limits
AWS SSM Cloud-managed tunnel EC2 access without open SSH ports No SSH port needed, IAM auth, audit logging AWS-only, requires SSM agent, higher latency
Teleport Zero-trust access gateway Enterprise SSH/K8s/DB access with SSO Certificate-based, audit trail, SSO integration Complex setup, enterprise pricing
Tailscale / ZeroTier Mesh VPN (overlay) Connecting devices across networks Easy peer-to-peer, NAT traversal, no server config Third-party control plane, not fully self-hosted

When to use SSH tunnels: Quick, ad-hoc port access to a single service through an existing SSH server. When to consider alternatives: Full network access (WireGuard), public-facing endpoints (ngrok), enterprise compliance (Teleport), or multi-device mesh (Tailscale).