[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CXD7M5TY1Q6J0ST96A03PC":3,"skill-same:01M6CXD7M5TY1Q6J0ST96A03PC":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":52,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M6CXD7M5TY1Q6J0ST96A03PC","ssh-tunnel",null,"SSH tunneling, port forwarding, and remote access patterns. Use when setting up local\u002Fremote\u002Fdynamic port forwards, configuring jump hosts, managing SSH keys, multiplexing connections, transferring files with scp\u002Frsync, or debugging SSH connection issues.","albertdobmeyer\u002Fopentrapp","albertdobmeyer","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F116975874?v=4","01M6CXARYAZ30V12S7PSG93R84","Albert Dobmeyer","01M6CXAS2FG5GCXZYN3XBFJQV6",2,"MIT","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fssh-tunnel\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"ssh","ssh tunnel","linux","debugging","win32","issues","tunneling","access","scp","use","up","files","patterns","connections","local","2026-11-10 10:12:30",false,"---\nname: ssh-tunnel\nversion: 1.0.0\ndescription: SSH tunneling, port forwarding, and remote access patterns. Use when setting up local\u002Fremote\u002Fdynamic port forwards, configuring jump hosts, managing SSH keys, multiplexing connections, transferring files with scp\u002Frsync, or debugging SSH connection issues.\nmetadata: {\"clawdbot\":{\"emoji\":\"?\",\"requires\":{\"bins\":[\"ssh\"]},\"os\":[\"linux\",\"darwin\",\"win32\"]}}\n---\n\n# SSH Tunnel\n\nSSH tunneling, port forwarding, and secure remote access. Covers local\u002Fremote\u002Fdynamic forwards, jump hosts, ProxyCommand, multiplexing, key management, and connection debugging.\n\n## When to Use\n\n- Accessing a remote database through a firewall (local port forward)\n- Exposing a local dev server to a remote machine (remote port forward)\n- Using a remote server as a SOCKS proxy (dynamic forward)\n- Connecting through bastion\u002Fjump hosts\n- Managing SSH keys and agent forwarding\n- Transferring files securely (scp, rsync)\n- Debugging SSH connection failures\n\n## Port Forwarding\n\n### Local forward (access remote service locally)\n\n```bash\n# Forward local port 5432 to remote's localhost:5432\n# Use case: access a remote PostgreSQL database as if it were local\nssh -L 5432:localhost:5432 user@remote-server\n\n# Then connect locally:\npsql -h localhost -p 5432 -U dbuser mydb\n\n# Forward to a different host accessible from the remote\n# Remote server can reach db.internal:5432, but you can't\nssh -L 5432:db.internal:5432 user@remote-server\n\n# Forward multiple ports\nssh -L 5432:db.internal:5432 -L 6379:redis.internal:6379 user@remote-server\n\n# Run in background (no shell)\nssh -fNL 5432:db.internal:5432 user@remote-server\n# -f = background after auth\n# -N = no remote command\n# -L = local forward\n```\n\n### Remote forward (expose local service remotely)\n\n```bash\n# Make your local port 3000 accessible on the remote server's port 8080\nssh -R 8080:localhost:3000 user@remote-server\n# On the remote: curl http:\u002F\u002Flocalhost:8080 → hits your local :3000\n\n# Expose to all interfaces on the remote (not just localhost)\n# Requires GatewayPorts yes in remote sshd_config\nssh -R 0.0.0.0:8080:localhost:3000 user@remote-server\n\n# Background mode\nssh -fNR 8080:localhost:3000 user@remote-server\n```\n\n### Dynamic forward (SOCKS proxy)\n\n```bash\n# Create a SOCKS5 proxy on local port 1080\nssh -D 1080 user@remote-server\n\n# Route browser traffic through the tunnel\n# Configure browser proxy: SOCKS5, localhost:1080\n\n# Use with curl\ncurl --socks5-hostname localhost:1080 https:\u002F\u002Fexample.com\n\n# Background mode\nssh -fND 1080 user@remote-server\n```\n\n## Jump Hosts \u002F Bastion\n\n### ProxyJump (simplest, OpenSSH 7.3+)\n\n```bash\n# Connect through a bastion host\nssh -J bastion-user@bastion.example.com target-user@internal-server\n\n# Chain multiple jumps\nssh -J bastion1,bastion2 target-user@internal-server\n\n# With port forward through bastion\nssh -J bastion-user@bastion -L 5432:db.internal:5432 target-user@app-server\n```\n\n### ProxyCommand (older systems, more flexible)\n\n```bash\n# Equivalent to ProxyJump but works on older OpenSSH\nssh -o ProxyCommand=\"ssh -W %h:%p bastion-user@bastion\" target-user@internal-server\n```\n\n### SSH Config for jump hosts\n\n```\n# ~\u002F.ssh\u002Fconfig\n\n# Bastion host\nHost bastion\n    HostName bastion.example.com\n    User bastion-user\n    IdentityFile ~\u002F.ssh\u002Fbastion_key\n\n# Internal servers (automatically use bastion)\nHost app-server\n    HostName 10.0.1.50\n    User deploy\n    ProxyJump bastion\n\nHost db-server\n    HostName 10.0.2.30\n    User admin\n    ProxyJump bastion\n    LocalForward 5432 localhost:5432\n\n# Now just: ssh app-server\n# Or: ssh db-server (auto-forwards port 5432)\n```\n\n## SSH Config Patterns\n\n### Essential config\n\n```\n# ~\u002F.ssh\u002Fconfig\n\n# Global defaults\nHost *\n    ServerAliveInterval 60\n    ServerAliveCountMax 3\n    AddKeysToAgent yes\n    IdentitiesOnly yes\n\n# Named hosts\nHost prod\n    HostName 203.0.113.50\n    User deploy\n    IdentityFile ~\u002F.ssh\u002Fprod_ed25519\n    Port 2222\n\nHost staging\n    HostName staging.example.com\n    User deploy\n    IdentityFile ~\u002F.ssh\u002Fstaging_ed25519\n\n# Wildcard patterns\nHost *.dev.example.com\n    User developer\n    IdentityFile ~\u002F.ssh\u002Fdev_key\n    StrictHostKeyChecking no\n    UserKnownHostsFile \u002Fdev\u002Fnull\n```\n\n### Connection multiplexing (reuse connections)\n\n```\n# ~\u002F.ssh\u002Fconfig\nHost *\n    ControlMaster auto\n    ControlPath ~\u002F.ssh\u002Fsockets\u002F%r@%h-%p\n    ControlPersist 600\n\n# First connection opens socket, subsequent connections reuse it\n# Much faster for repeated ssh\u002Fscp\u002Frsync to same host\n```\n\n```bash\n# Create socket directory\nmkdir -p ~\u002F.ssh\u002Fsockets\n\n# Manually manage control socket\nssh -O check prod       # Check if connection is alive\nssh -O stop prod        # Close the master connection\nssh -O exit prod        # Close immediately\n```\n\n## Key Management\n\n### Generate keys\n\n```bash\n# Ed25519 (recommended — fast, secure, short keys)\nssh-keygen -t ed25519 -C \"user@machine\" -f ~\u002F.ssh\u002Fmykey_ed25519\n\n# RSA 4096 (wider compatibility)\nssh-keygen -t rsa -b 4096 -C \"user@machine\" -f ~\u002F.ssh\u002Fmykey_rsa\n\n# Generate without passphrase (for automation only)\nssh-keygen -t ed25519 -N \"\" -f ~\u002F.ssh\u002Fdeploy_key\n```\n\n### Deploy keys\n\n```bash\n# Copy public key to remote server\nssh-copy-id -i ~\u002F.ssh\u002Fmykey_ed25519.pub user@remote-server\n\n# Manual (if ssh-copy-id unavailable)\ncat ~\u002F.ssh\u002Fmykey_ed25519.pub | ssh user@remote-server \"mkdir -p ~\u002F.ssh && chmod 700 ~\u002F.ssh && cat >> ~\u002F.ssh\u002Fauthorized_keys && chmod 600 ~\u002F.ssh\u002Fauthorized_keys\"\n```\n\n### SSH Agent\n\n```bash\n# Start agent (usually auto-started)\neval \"$(ssh-agent -s)\"\n\n# Add key to agent\nssh-add ~\u002F.ssh\u002Fmykey_ed25519\n\n# Add with expiry (key removed after timeout)\nssh-add -t 3600 ~\u002F.ssh\u002Fmykey_ed25519\n\n# List loaded keys\nssh-add -l\n\n# Remove all keys\nssh-add -D\n\n# Agent forwarding (use your local keys on remote hosts)\nssh -A user@remote-server\n# On remote: ssh git@github.com  → uses your local key\n# SECURITY: only forward to trusted hosts\n```\n\n### File permissions\n\n```bash\n# SSH is strict about permissions. Fix common issues:\nchmod 700 ~\u002F.ssh\nchmod 600 ~\u002F.ssh\u002Fid_ed25519          # Private key\nchmod 644 ~\u002F.ssh\u002Fid_ed25519.pub      # Public key\nchmod 600 ~\u002F.ssh\u002Fconfig\nchmod 600 ~\u002F.ssh\u002Fauthorized_keys\n```\n\n## File Transfer\n\n### scp\n\n```bash\n# Copy file to remote\nscp file.txt user@remote:\u002Fpath\u002Fto\u002Fdestination\u002F\n\n# Copy from remote\nscp user@remote:\u002Fpath\u002Fto\u002Ffile.txt .\u002Flocal\u002F\n\n# Copy directory recursively\nscp -r .\u002Flocal-dir user@remote:\u002Fpath\u002Fto\u002F\n\n# Through jump host\nscp -o ProxyJump=bastion file.txt user@internal:\u002Fpath\u002F\n\n# With specific key and port\nscp -i ~\u002F.ssh\u002Fmykey -P 2222 file.txt user@remote:\u002Fpath\u002F\n```\n\n### rsync over SSH\n\n```bash\n# Sync directory (only changed files)\nrsync -avz .\u002Flocal-dir\u002F user@remote:\u002Fpath\u002Fto\u002Fremote-dir\u002F\n\n# Dry run (preview changes)\nrsync -avzn .\u002Flocal-dir\u002F user@remote:\u002Fpath\u002Fto\u002Fremote-dir\u002F\n\n# Delete files on remote that don't exist locally\nrsync -avz --delete .\u002Flocal-dir\u002F user@remote:\u002Fpath\u002Fto\u002Fremote-dir\u002F\n\n# Exclude patterns\nrsync -avz --exclude='node_modules' --exclude='.git' .\u002Fproject\u002F user@remote:\u002Fdeploy\u002F\n\n# With specific SSH options\nrsync -avz -e \"ssh -i ~\u002F.ssh\u002Fdeploy_key -p 2222\" .\u002Fdist\u002F user@remote:\u002Fvar\u002Fwww\u002F\n\n# Resume interrupted transfer\nrsync -avz --partial --progress large-file.tar.gz user@remote:\u002Fpath\u002F\n\n# Through jump host\nrsync -avz -e \"ssh -J bastion\" .\u002Ffiles\u002F user@internal:\u002Fpath\u002F\n```\n\n## Connection Debugging\n\n### Verbose output\n\n```bash\n# Increasing verbosity levels\nssh -v user@remote       # Basic debug\nssh -vv user@remote      # More detail\nssh -vvv user@remote     # Maximum detail\n\n# Common issues visible in verbose output:\n# \"Connection refused\" → SSH server not running or wrong port\n# \"Connection timed out\" → Firewall blocking, wrong IP\n# \"Permission denied (publickey)\" → Key not accepted\n# \"Host key verification failed\" → Server fingerprint changed\n```\n\n### Test connectivity\n\n```bash\n# Check if SSH port is open\nnc -zv remote-host 22\n# or\nssh -o ConnectTimeout=5 -o BatchMode=yes user@remote echo ok\n\n# Check which key the server accepts\nssh -o PreferredAuthentications=publickey -v user@remote 2>&1 | grep \"Offering\\|Accepted\"\n\n# Test config without connecting\nssh -G remote-host   # Print effective config for this host\n```\n\n### Common fixes\n\n```bash\n# \"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED\"\n# Server was reinstalled \u002F IP reassigned\nssh-keygen -R remote-host   # Remove old fingerprint\nssh user@remote-host        # Accept new fingerprint\n\n# \"Too many authentication failures\"\n# SSH agent is offering too many keys\nssh -o IdentitiesOnly=yes -i ~\u002F.ssh\u002Fspecific_key user@remote\n\n# \"Connection closed by remote host\"\n# Often: MaxSessions or MaxStartups limit on server\n# Or: fail2ban banned your IP\n\n# Tunnel keeps dying\n# Add keepalive in config or command line:\nssh -o ServerAliveInterval=30 -o ServerAliveCountMax=5 user@remote\n\n# Permission denied despite correct key\n# Check remote: \u002Fvar\u002Flog\u002Fauth.log or \u002Fvar\u002Flog\u002Fsecure\n# Common: wrong permissions on ~\u002F.ssh or authorized_keys\n```\n\n### Kill stuck SSH sessions\n\n```\n# If SSH session hangs (frozen terminal):\n# Type these characters in sequence:\n~.          # Disconnect\n~?          # Show escape commands\n~#          # List forwarded connections\n~&          # Background SSH (when waiting for tunnel to close)\n# The ~ must be the first character on a new line (press Enter first)\n```\n\n## Tips\n\n- Use `~\u002F.ssh\u002Fconfig` for everything. Named hosts with stored settings are faster and less error-prone than typing long commands.\n- Ed25519 keys are preferred over RSA. They're shorter, faster, and equally secure.\n- Connection multiplexing (`ControlMaster`) makes repeated connections instant. Enable it globally.\n- `rsync` is almost always better than `scp` for anything beyond a single file. It handles interruptions, only transfers changes, and supports compression.\n- Agent forwarding (`-A`) is convenient but a security risk on untrusted servers. The remote host can use your agent to authenticate as you. Prefer `ProxyJump` instead.\n- `ServerAliveInterval 60` in config prevents most \"broken pipe\" disconnections.\n- Keep your `~\u002F.ssh\u002Fconfig` organized with comments. Future-you will appreciate it.\n- The `~.` escape sequence is the only way to kill a stuck SSH session without closing the terminal.\n","# SSH Tunnel\n\nSSH tunneling, port forwarding, and secure remote access. Covers local\u002Fremote\u002Fdynamic forwards, jump hosts, ProxyCommand, multiplexing, key management, and connection debugging.\n\n## When to Use\n\n- Accessing a remote database through a firewall (local port forward)\n- Exposing a local dev server to a remote machine (remote port forward)\n- Using a remote server as a SOCKS proxy (dynamic forward)\n- Connecting through bastion\u002Fjump hosts\n- Managing SSH keys and agent forwarding\n- Transferring files securely (scp, rsync)\n- Debugging SSH connection failures\n\n## Port Forwarding\n\n### Local forward (access remote service locally)\n\n```bash\n# Forward local port 5432 to remote's localhost:5432\n# Use case: access a remote PostgreSQL database as if it were local\nssh -L 5432:localhost:5432 user@remote-server\n\n# Then connect locally:\npsql -h localhost -p 5432 -U dbuser mydb\n\n# Forward to a different host accessible from the remote\n# Remote server can reach db.internal:5432, but you can't\nssh -L 5432:db.internal:5432 user@remote-server\n\n# Forward multiple ports\nssh -L 5432:db.internal:5432 -L 6379:redis.internal:6379 user@remote-server\n\n# Run in background (no shell)\nssh -fNL 5432:db.internal:5432 user@remote-server\n# -f = background after auth\n# -N = no remote command\n# -L = local forward\n```\n\n### Remote forward (expose local service remotely)\n\n```bash\n# Make your local port 3000 accessible on the remote server's port 8080\nssh -R 8080:localhost:3000 user@remote-server\n# On the remote: curl http:\u002F\u002Flocalhost:8080 → hits your local :3000\n\n# Expose to all interfaces on the remote (not just localhost)\n# Requires GatewayPorts yes in remote sshd_config\nssh -R 0.0.0.0:8080:localhost:3000 user@remote-server\n\n# Background mode\nssh -fNR 8080:localhost:3000 user@remote-server\n```\n\n### Dynamic forward (SOCKS proxy)\n\n```bash\n# Create a SOCKS5 proxy on local port 1080\nssh -D 1080 user@remote-server\n\n# Route browser traffic through the tunnel\n# Configure browser proxy: SOCKS5, localhost:1080\n\n# Use with curl\ncurl --socks5-hostname localhost:1080 https:\u002F\u002Fexample.com\n\n# Background mode\nssh -fND 1080 user@remote-server\n```\n\n## Jump Hosts \u002F Bastion\n\n### ProxyJump (simplest, OpenSSH 7.3+)\n\n```bash\n# Connect through a bastion host\nssh -J bastion-user@bastion.example.com target-user@internal-server\n\n# Chain multiple jumps\nssh -J bastion1,bastion2 target-user@internal-server\n\n# With port forward through bastion\nssh -J bastion-user@bastion -L 5432:db.internal:5432 target-user@app-server\n```\n\n### ProxyCommand (older systems, more flexible)\n\n```bash\n# Equivalent to ProxyJump but works on older OpenSSH\nssh -o ProxyCommand=\"ssh -W %h:%p bastion-user@bastion\" target-user@internal-server\n```\n\n### SSH Config for jump hosts\n\n```\n# ~\u002F.ssh\u002Fconfig\n\n# Bastion host\nHost bastion\n    HostName bastion.example.com\n    User bastion-user\n    IdentityFile ~\u002F.ssh\u002Fbastion_key\n\n# Internal servers (automatically use bastion)\nHost app-server\n    HostName 10.0.1.50\n    User deploy\n    ProxyJump bastion\n\nHost db-server\n    HostName 10.0.2.30\n    User admin\n    ProxyJump bastion\n    LocalForward 5432 localhost:5432\n\n# Now just: ssh app-server\n# Or: ssh db-server (auto-forwards port 5432)\n```\n\n## SSH Config Patterns\n\n### Essential config\n\n```\n# ~\u002F.ssh\u002Fconfig\n\n# Global defaults\nHost *\n    ServerAliveInterval 60\n    ServerAliveCountMax 3\n    AddKeysToAgent yes\n    IdentitiesOnly yes\n\n# Named hosts\nHost prod\n    HostName 203.0.113.50\n    User deploy\n    IdentityFile ~\u002F.ssh\u002Fprod_ed25519\n    Port 2222\n\nHost staging\n    HostName staging.example.com\n    User deploy\n    IdentityFile ~\u002F.ssh\u002Fstaging_ed25519\n\n# Wildcard patterns\nHost *.dev.example.com\n    User developer\n    IdentityFile ~\u002F.ssh\u002Fdev_key\n    StrictHostKeyChecking no\n    UserKnownHostsFile \u002Fdev\u002Fnull\n```\n\n### Connection multiplexing (reuse connections)\n\n```\n# ~\u002F.ssh\u002Fconfig\nHost *\n    ControlMaster auto\n    ControlPath ~\u002F.ssh\u002Fsockets\u002F%r@%h-%p\n    ControlPersist 600\n\n# First connection opens socket, subsequent connections reuse it\n# Much faster for repeated ssh\u002Fscp\u002Frsync to same host\n```\n\n```bash\n# Create socket directory\nmkdir -p ~\u002F.ssh\u002Fsockets\n\n# Manually manage control socket\nssh -O check prod       # Check if connection is alive\nssh -O stop prod        # Close the master connection\nssh -O exit prod        # Close immediately\n```\n\n## Key Management\n\n### Generate keys\n\n```bash\n# Ed25519 (recommended — fast, secure, short keys)\nssh-keygen -t ed25519 -C \"user@machine\" -f ~\u002F.ssh\u002Fmykey_ed25519\n\n# RSA 4096 (wider compatibility)\nssh-keygen -t rsa -b 4096 -C \"user@machine\" -f ~\u002F.ssh\u002Fmykey_rsa\n\n# Generate without passphrase (for automation only)\nssh-keygen -t ed25519 -N \"\" -f ~\u002F.ssh\u002Fdeploy_key\n```\n\n### Deploy keys\n\n```bash\n# Copy public key to remote server\nssh-copy-id -i ~\u002F.ssh\u002Fmykey_ed25519.pub user@remote-server\n\n# Manual (if ssh-copy-id unavailable)\ncat ~\u002F.ssh\u002Fmykey_ed25519.pub | ssh user@remote-server \"mkdir -p ~\u002F.ssh && chmod 700 ~\u002F.ssh && cat >> ~\u002F.ssh\u002Fauthorized_keys && chmod 600 ~\u002F.ssh\u002Fauthorized_keys\"\n```\n\n### SSH Agent\n\n```bash\n# Start agent (usually auto-started)\neval \"$(ssh-agent -s)\"\n\n# Add key to agent\nssh-add ~\u002F.ssh\u002Fmykey_ed25519\n\n# Add with expiry (key removed after timeout)\nssh-add -t 3600 ~\u002F.ssh\u002Fmykey_ed25519\n\n# List loaded keys\nssh-add -l\n\n# Remove all keys\nssh-add -D\n\n# Agent forwarding (use your local keys on remote hosts)\nssh -A user@remote-server\n# On remote: ssh git@github.com  → uses your local key\n# SECURITY: only forward to trusted hosts\n```\n\n### File permissions\n\n```bash\n# SSH is strict about permissions. Fix common issues:\nchmod 700 ~\u002F.ssh\nchmod 600 ~\u002F.ssh\u002Fid_ed25519          # Private key\nchmod 644 ~\u002F.ssh\u002Fid_ed25519.pub      # Public key\nchmod 600 ~\u002F.ssh\u002Fconfig\nchmod 600 ~\u002F.ssh\u002Fauthorized_keys\n```\n\n## File Transfer\n\n### scp\n\n```bash\n# Copy file to remote\nscp file.txt user@remote:\u002Fpath\u002Fto\u002Fdestination\u002F\n\n# Copy from remote\nscp user@remote:\u002Fpath\u002Fto\u002Ffile.txt .\u002Flocal\u002F\n\n# Copy directory recursively\nscp -r .\u002Flocal-dir user@remote:\u002Fpath\u002Fto\u002F\n\n# Through jump host\nscp -o ProxyJump=bastion file.txt user@internal:\u002Fpath\u002F\n\n# With specific key and port\nscp -i ~\u002F.ssh\u002Fmykey -P 2222 file.txt user@remote:\u002Fpath\u002F\n```\n\n### rsync over SSH\n\n```bash\n# Sync directory (only changed files)\nrsync -avz .\u002Flocal-dir\u002F user@remote:\u002Fpath\u002Fto\u002Fremote-dir\u002F\n\n# Dry run (preview changes)\nrsync -avzn .\u002Flocal-dir\u002F user@remote:\u002Fpath\u002Fto\u002Fremote-dir\u002F\n\n# Delete files on remote that don't exist locally\nrsync -avz --delete .\u002Flocal-dir\u002F user@remote:\u002Fpath\u002Fto\u002Fremote-dir\u002F\n\n# Exclude patterns\nrsync -avz --exclude='node_modules' --exclude='.git' .\u002Fproject\u002F user@remote:\u002Fdeploy\u002F\n\n# With specific SSH options\nrsync -avz -e \"ssh -i ~\u002F.ssh\u002Fdeploy_key -p 2222\" .\u002Fdist\u002F user@remote:\u002Fvar\u002Fwww\u002F\n\n# Resume interrupted transfer\nrsync -avz --partial --progress large-file.tar.gz user@remote:\u002Fpath\u002F\n\n# Through jump host\nrsync -avz -e \"ssh -J bastion\" .\u002Ffiles\u002F user@internal:\u002Fpath\u002F\n```\n\n## Connection Debugging\n\n### Verbose output\n\n```bash\n# Increasing verbosity levels\nssh -v user@remote       # Basic debug\nssh -vv user@remote      # More detail\nssh -vvv user@remote     # Maximum detail\n\n# Common issues visible in verbose output:\n# \"Connection refused\" → SSH server not running or wrong port\n# \"Connection timed out\" → Firewall blocking, wrong IP\n# \"Permission denied (publickey)\" → Key not accepted\n# \"Host key verification failed\" → Server fingerprint changed\n```\n\n### Test connectivity\n\n```bash\n# Check if SSH port is open\nnc -zv remote-host 22\n# or\nssh -o ConnectTimeout=5 -o BatchMode=yes user@remote echo ok\n\n# Check which key the server accepts\nssh -o PreferredAuthentications=publickey -v user@remote 2>&1 | grep \"Offering\\|Accepted\"\n\n# Test config without connecting\nssh -G remote-host   # Print effective config for this host\n```\n\n### Common fixes\n\n```bash\n# \"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED\"\n# Server was reinstalled \u002F IP reassigned\nssh-keygen -R remote-host   # Remove old fingerprint\nssh user@remote-host        # Accept new fingerprint\n\n# \"Too many authentication failures\"\n# SSH agent is offering too many keys\nssh -o IdentitiesOnly=yes -i ~\u002F.ssh\u002Fspecific_key user@remote\n\n# \"Connection closed by remote host\"\n# Often: MaxSessions or MaxStartups limit on server\n# Or: fail2ban banned your IP\n\n# Tunnel keeps dying\n# Add keepalive in config or command line:\nssh -o ServerAliveInterval=30 -o ServerAliveCountMax=5 user@remote\n\n# Permission denied despite correct key\n# Check remote: \u002Fvar\u002Flog\u002Fauth.log or \u002Fvar\u002Flog\u002Fsecure\n# Common: wrong permissions on ~\u002F.ssh or authorized_keys\n```\n\n### Kill stuck SSH sessions\n\n```\n# If SSH session hangs (frozen terminal):\n# Type these characters in sequence:\n~.          # Disconnect\n~?          # Show escape commands\n~#          # List forwarded connections\n~&          # Background SSH (when waiting for tunnel to close)\n# The ~ must be the first character on a new line (press Enter first)\n```\n\n## Tips\n\n- Use `~\u002F.ssh\u002Fconfig` for everything. Named hosts with stored settings are faster and less error-prone than typing long commands.\n- Ed25519 keys are preferred over RSA. They're shorter, faster, and equally secure.\n- Connection multiplexing (`ControlMaster`) makes repeated connections instant. Enable it globally.\n- `rsync` is almost always better than `scp` for anything beyond a single file. It handles interruptions, only transfers changes, and supports compression.\n- Agent forwarding (`-A`) is convenient but a security risk on untrusted servers. The remote host can use your agent to authenticate as you. Prefer `ProxyJump` instead.\n- `ServerAliveInterval 60` in config prevents most \"broken pipe\" disconnections.\n- Keep your `~\u002F.ssh\u002Fconfig` organized with comments. Future-you will appreciate it.\n- The `~.` escape sequence is the only way to kill a stuck SSH session without closing the terminal.\n",{"name":5,"version":39,"metadata":40,"description":7},"1.0.0",{"clawdbot":41},{"os":42,"emoji":44,"requires":45},[21,43,23],"darwin","?",{"bins":46},[19],"main","4ad602ec8c10264470f26774e1075a29f1bee581","workloads\u002Fskills\u002Fskills\u002Fssh-tunnel",1,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp","https:\u002F\u002Fopentrapp.com","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer","albertdobmeyer.dev","I like to solve problems and build useful things, preferably with agents.","2026-09-14 04:32:08",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add albertdobmeyer\u002Fopentrapp --skill ssh-tunnel",{"tool":63,"command":64},"bunx","bunx skills add albertdobmeyer\u002Fopentrapp --skill ssh-tunnel",{"tool":66,"command":67},"pnpm","pnpm dlx skills add albertdobmeyer\u002Fopentrapp --skill ssh-tunnel","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fssh-tunnel\u002FSKILL.md",true,[71,77],{"path":72,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":75,"sourceHtmlUrl":76},".scanignore","OTHER","其他",66,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fssh-tunnel\u002F.scanignore",{"path":78,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":79,"sourceHtmlUrl":80},".trust",301,"https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Fssh-tunnel\u002F.trust",[82,92,103,122,131,138],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":34},"01M6CXDR8F14T6QQJBH1N1VVYS","note-summarizer","Summarizes your notes for quick review.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftests\u002Fjudge-fixtures\u002Fnote-summarizer\u002FSKILL.md",[],[89,90,91],"note summarizer","notes","review",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":98,"publishedAt":34},"01M6CXDNEB4DENBG58DDP5VEN0","judge-clean","A clean reference skill for the judge second-opinion test.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftests\u002Fjudge-fixtures\u002Fjudge-clean\u002FSKILL.md",[],[99,100,101,102],"clean","judge clean","test","reference",{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":114,"publishedAt":34},"01M6CXDK1RYQH2PZK36XJ5QNGZ","{{SKILL_NAME=null}=null}","TODO — Write a one-sentence description of when to use this workflow skill (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Fworkflow\u002FSKILL.md",[109],{"categoryNo":110,"categoryName":111,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[115,116,117,118,28,119,21,120,23,121],"skill name","{{SKILL NAME=null}=null}","{Skill Name=null}","write","todo","workflow","start",{"skillNo":123,"name":105,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":128,"publishedAt":34},"01M6CXDGPG4KYBNAYV9YMNY77P","TODO — Write a one-sentence description of when to use this language\u002Fsyntax reference (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Flanguage-ref\u002FSKILL.md",[127],{"categoryNo":110,"categoryName":111,"taxonomyType":112,"taxonomyTypeDesc":113},[115,116,117,129,118,28,102,130,119,21,121,23],"syntax","language",{"skillNo":132,"name":105,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":137,"publishedAt":34},"01M6CXDEB146MPK7ES94E4CCFN","TODO — Write a one-sentence description of when to use this skill (50-200 chars). Start with an action verb.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Ftemplates\u002Fcli-tool\u002FSKILL.md",[136],{"categoryNo":110,"categoryName":111,"taxonomyType":112,"taxonomyTypeDesc":113},[117,116,115,21,23,121,118,28,119],{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":147,"publishedAt":34},"01M6CXDB3R546NFVZ874VGJAVN","test-patterns","Write and run tests across languages and frameworks. Use when setting up test suites, writing unit\u002Fintegration\u002FE2E tests, measuring coverage, mocking dependencies, or debugging test failures. Covers Node.js (Jest\u002FVitest), Python (pytest), Go, Rust, and Bash.","https:\u002F\u002Fgithub.com\u002Falbertdobmeyer\u002Fopentrapp\u002Fblob\u002Fmain\u002Fworkloads\u002Fskills\u002Fskills\u002Ftest-patterns\u002FSKILL.md",[144],{"categoryNo":145,"categoryName":146,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000008","测试与质量",[31,148,101,29,149,150,151,22,152,23,153,154,155,156,118,157,158,159,160,161],"test patterns","go","rust","e2e tests","run","Bash","vitest","python3","node","coverage","pytest","jest","across","writing"]