名称: ssh-tunnel
描述: SSH 隧道、端口转发与远程访问模式。适用于设置本地/远程/动态端口转发、配置跳板主机、管理 SSH 密钥、复用连接、使用 scp/rsync 传输文件或调试 SSH 连接问题。
元数据: {"clawdbot":{"emoji":"🔑","requires":{"bins":["ssh"]},"os":["linux","darwin","win32"]}}
SSH 隧道、端口转发与安全远程访问。涵盖本地/远程/动态转发、跳板主机、ProxyCommand、连接复用、密钥管理与连接调试。
# 将本地端口 5432 转发到远程的 localhost:5432
# 用例:像访问本地数据库一样访问远程 PostgreSQL
ssh -L 5432:localhost:5432 user@remote-server
# 然后在本地连接:
psql -h localhost -p 5432 -U dbuser mydb
# 转发到远程可访问的其他主机
# 远程服务器能访问 db.internal:5432,但你无法直接访问
ssh -L 5432:db.internal:5432 user@remote-server
# 转发多个端口
ssh -L 5432:db.internal:5432 -L 6379:redis.internal:6379 user@remote-server
# 在后台运行(不打开 shell)
ssh -fNL 5432:db.internal:5432 user@remote-server
# -f = 认证后转入后台
# -N = 不执行远程命令
# -L = 本地转发
# 使你的本地端口 3000 可在远程服务器的 8080 端口访问
ssh -R 8080:localhost:3000 user@remote-server
# 在远程执行:curl http://localhost:8080 → 访问你的本地 :3000
# 暴露给远程的所有接口(不仅是 localhost)
# 需要在远程 sshd_config 中设置 GatewayPorts yes
ssh -R 0.0.0.0:8080:localhost:3000 user@remote-server
# 后台模式
ssh -fNR 8080:localhost:3000 user@remote-server
# 在本地端口 1080 创建 SOCKS5 代理
ssh -D 1080 user@remote-server
# 通过隧道路由浏览器流量
# 浏览器代理配置:SOCKS5,localhost:1080
# 与 curl 配合使用
curl --socks5-hostname localhost:1080 https://example.com
# 后台模式
ssh -fND 1080 user@remote-server
# 通过堡垒机连接
ssh -J bastion-user@bastion.example.com target-user@internal-server
# 链式多跳
ssh -J bastion1,bastion2 target-user@internal-server
# 通过堡垒机进行端口转发
ssh -J bastion-user@bastion -L 5432:db.internal:5432 target-user@app-server
# 等同于 ProxyJump,但兼容旧版 OpenSSH
ssh -o ProxyCommand="ssh -W %h:%p bastion-user@bastion" target-user@internal-server
# ~/.ssh/config
# 堡垒机
Host bastion
HostName bastion.example.com
User bastion-user
IdentityFile ~/.ssh/bastion_key
# 内部服务器(自动使用堡垒机)
Host app-server
HostName 10.0.1.50
User deploy
ProxyJump bastion
Host db-server
HostName 10.0.2.30
User admin
ProxyJump bastion
LocalForward 5432 localhost:5432
# 现在只需:ssh app-server
# 或:ssh db-server(自动转发端口 5432)
# ~/.ssh/config
# 全局默认设置
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
IdentitiesOnly yes
# 命名主机
Host prod
HostName 203.0.113.50
User deploy
IdentityFile ~/.ssh/prod_ed25519
Port 2222
Host staging
HostName staging.example.com
User deploy
IdentityFile ~/.ssh/staging_ed25519
# 通配符模式
Host *.dev.example.com
User developer
IdentityFile ~/.ssh/dev_key
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
# ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
# 首次连接创建 socket,后续连接复用
# 对同一主机的重复 ssh/scp/rsync 操作会快很多
# 创建 socket 目录
mkdir -p ~/.ssh/sockets
# 手动管理控制 socket
ssh -O check prod # 检查连接是否存活
ssh -O stop prod # 关闭主连接
ssh -O exit prod # 立即关闭
# Ed25519(推荐 — 快速、安全、密钥短)
ssh-keygen -t ed25519 -C "user@machine" -f ~/.ssh/mykey_ed25519
# RSA 4096(兼容性更广)
ssh-keygen -t rsa -b 4096 -C "user@machine" -f ~/.ssh/mykey_rsa
# 生成无密码密钥(仅用于自动化)
ssh-keygen -t ed25519 -N "" -f ~/.ssh/deploy_key
# 复制公钥到远程服务器
ssh-copy-id -i ~/.ssh/mykey_ed25519.pub user@remote-server
# 手动部署(如果 ssh-copy-id 不可用)
cat ~/.ssh/mykey_ed25519.pub | ssh user@remote-server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# 启动代理(通常自动启动)
eval "$(ssh-agent -s)"
# 添加密钥到代理
ssh-add ~/.ssh/mykey_ed25519
# 添加带过期时间的密钥(超时后移除)
ssh-add -t 3600 ~/.ssh/mykey_ed25519
# 列出已加载的密钥
ssh-add -l
# 移除所有密钥
ssh-add -D
# 代理转发(在远程主机上使用你的本地密钥)
ssh -A user@remote-server
# 在远程执行:ssh git@github.com → 使用你的本地密钥
# 安全提示:仅转发到受信任的主机
# SSH 对权限要求严格。修复常见问题:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 # 私钥
chmod 644 ~/.ssh/id_ed25519.pub # 公钥
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/authorized_keys
# 复制文件到远程
scp file.txt user@remote:/path/to/destination/
# 从远程复制文件
scp user@remote:/path/to/file.txt ./local/
# 递归复制目录
scp -r ./local-dir user@remote:/path/to/
# 通过跳板主机
scp -o ProxyJump=bastion file.txt user@internal:/path/
# 使用指定密钥和端口
scp -i ~/.ssh/mykey -P 2222 file.txt user@remote:/path/
# 同步目录(仅传输更改的文件)
rsync -avz ./local-dir/ user@remote:/path/to/remote-dir/
# 试运行(预览更改)
rsync -avzn ./local-dir/ user@remote:/path/to/remote-dir/
# 删除远程不存在于本地的文件
rsync -avz --delete ./local-dir/ user@remote:/path/to/remote-dir/
# 排除特定模式
rsync -avz --exclude='node_modules' --exclude='.git' ./project/ user@remote:/deploy/
# 使用特定 SSH 选项
rsync -avz -e "ssh -i ~/.ssh/deploy_key -p 2222" ./dist/ user@remote:/var/www/
# 恢复中断的传输
rsync -avz --partial --progress large-file.tar.gz user@remote:/path/
# 通过跳板主机
rsync -avz -e "ssh -J bastion" ./files/ user@internal:/path/
# 递增详细级别
ssh -v user@remote # 基础调试
ssh -vv user@remote # 更多细节
ssh -vvv user@remote # 最大细节
# 详细输出中可见的常见问题:
# "Connection refused" → SSH 服务未运行或端口错误
# "Connection timed out" → 防火墙阻止或 IP 错误
# "Permission denied (publickey)" → 密钥未被接受
# "Host key verification failed" → 服务器指纹已更改
# 检查 SSH 端口是否开放
nc -zv remote-host 22
# 或
ssh -o ConnectTimeout=5 -o BatchMode=yes user@remote echo ok
# 检查服务器接受哪个密钥
ssh -o PreferredAuthentications=publickey -v user@remote 2>&1 | grep "Offering\|Accepted"
# 不连接测试配置
ssh -G remote-host # 打印该主机的有效配置
# "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED"
# 服务器已重装 / IP 已重新分配
ssh-keygen -R remote-host # 移除旧指纹
ssh user@remote-host # 接受新指纹
# "Too many authentication failures"
# SSH 代理提供了太多密钥
ssh -o IdentitiesOnly=yes -i ~/.ssh/specific_key user@remote
# "Connection closed by remote host"
# 常见原因:服务器上的 MaxSessions 或 MaxStartups 限制
# 或:fail2ban 封禁了你的 IP
# 隧道频繁断开
# 在配置或命令行中添加保活设置:
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=5 user@remote
# 密钥正确但权限被拒绝
# 检查远程日志:/var/log/auth.log 或 /var/log/secure
# 常见原因:~/.ssh 或 authorized_keys 权限错误
# 如果 SSH 会话挂起(终端冻结):
# 依次输入以下字符序列:
~. # 断开连接
~? # 显示转义命令
~# # 列出转发的连接
~& # 将 SSH 放入后台(等待隧道关闭时)
# ~ 必须是新行的第一个字符(先按 Enter)
~/.ssh/config 管理一切。使用命名主机和存储设置,比输入长命令更快且不易出错。ControlMaster)使重复连接瞬间完成。建议全局启用。rsync 几乎总是优于 scp。它能处理中断、仅传输更改并支持压缩。-A)很方便,但在不受信任的服务器上存在安全风险。远程主机可以使用你的代理以你的身份进行认证。建议优先使用 ProxyJump。ServerAliveInterval 60 可防止大多数“管道破裂”导致的断开。~/.ssh/config 的组织性。未来的你会感谢现在的你。~. 转义序列是终止卡住的 SSH 会话而不关闭终端的唯一方法。