SSH 跳板机怎么配:先把一次连接写成一行配置
SSH 跳板(也叫堡垒机、Jump Host)指的是你先连一台能被访问到的中转主机,再由它去连内部或远端的目标服务器。OpenSSH 提供的 ProxyJump 选项就是为这件事设计的:在 ~/.ssh/config 里写一行,之后 ssh 目标别名 就自动经过跳板,不必再手工登录两次。本文面向经常连远端开发机、云主机、公司内网服务器的开发者,内容对照 OpenSSH 官方 ssh_config 手册整理,重点放在「配得稳、连得快、断了好排查」。
跳板配置出问题时,表现往往是「第一次连很慢」「开了编辑器远程会话过一会儿就卡住」「scp 和 ssh 行为不一致」。这些问题多数不是网络本身坏了,而是配置没有把超时、复用和多跳顺序写清楚。下面分四块说明。
ProxyJump 的基本写法与多级跳板
ProxyJump 接受 [user@]host[:port] 或者 ssh URI 形式,多个跳板用逗号分隔,按顺序依次经过。命令行里对应的是 -J 参数,一次性使用很方便;长期使用建议写进配置文件。
单跳:一个别名搞定
下面这份配置定义了一台跳板和一台只能经跳板到达的目标机,主机名、网段都是示例,换成你自己的即可:
Host bastion
HostName 203.0.113.10
User ops
IdentityFile ~/.ssh/id_ed25519
Host dev-box
HostName 10.0.8.21
User dev
ProxyJump bastion
之后 ssh dev-box 就会先连 bastion 再转到 10.0.8.21。这里有一个常被忽略的点:ProxyJump 是在你本机上分别与每一跳建立 SSH 连接,认证用的是你本机的密钥,因此一般不需要开启 ForwardAgent 把本地的 agent 转发到跳板上,少开一个转发就少一份暴露面。
多跳:按顺序写在一行里
如果目标机在两层网络之后,可以写成 ProxyJump bastion1,bastion2,OpenSSH 会按先后顺序依次穿过。每一跳各自需要能认证通过,所以排查时要逐跳验证:先 ssh bastion1,再 ssh -J bastion1 bastion2,最后才是完整链路,哪一段失败一眼就能看出。别名里的 User、Port 也各自独立,不要指望目标机的用户名自动套用到跳板上。
ControlMaster:让第二次连接不再重新握手
每次 ssh、scp、git 走 SSH,都要重新做一遍 TCP 与加密握手,经过跳板时握手次数还会叠加。连接复用(Multiplexing)可以让后续会话共用第一条连接。手册对三个选项的说明可以归纳为:ControlMaster 开启共享,ControlPath 指定套接字位置,ControlPersist 让主连接在最后一个会话关闭后继续在后台保留一段时间。
Host *
ControlMaster auto
ControlPath ~/.ssh/cm/%C
ControlPersist 10m
这里用 %C 而不是手册里常见的 %r@%h:%p,原因是 Unix 域套接字的路径有长度上限,主机名或用户名较长时容易触发 too long for Unix domain socket 报错,%C 会把连接参数哈希成固定长度的字符串。使用前先执行 mkdir -p ~/.ssh/cm 建好目录并把权限设为 700。
复用连接断了怎么办
主连接异常中断后,残留的套接字文件有时会让新连接报 Control socket 相关错误。可以用 ssh -O check dev-box 查看主连接状态,ssh -O exit dev-box 主动关闭,必要时直接删除对应套接字文件再重连。如果你发现某条链路总是需要手工清理,说明主连接本身不稳定,应该回到保活参数上找原因。
超时与保活:决定「卡住」还是「快速失败」
默认情况下,连接一台不可达的主机要等系统的 TCP 超时,可能长达一两分钟。手册给出的 ConnectTimeout 就是用来替代系统默认超时的,ConnectionAttempts 则决定重试次数,每次间隔约一秒。对于脚本和自动化任务,两个参数一起设比较合理。
| 参数 | 作用 | 建议起点 |
|---|---|---|
| ConnectTimeout | 建立连接的等待上限(秒) | 10 到 15 |
| ConnectionAttempts | 连接失败后的重试次数 | 2 到 3,脚本场景用 |
| ServerAliveInterval | 空闲多少秒后发送保活探测 | 30 到 60 |
| ServerAliveCountMax | 连续几次探测无应答就断开,默认 3 | 3,链路抖动大时可调到 5 |
| ControlPersist | 主连接后台保留时间 | 10m |
要注意保活参数的取舍:间隔太短会在弱网下把轻微抖动误判成断线,间隔太长则长时间无响应才发现链路已死。更完整的保活机制可以参考SSH 远程连接总是莫名断开的 keepalive 科普。如果某一跳卡在 22 端口,也可以看看改走 443 的配置思路,原理同样适用于跳板的前置入口。
scp、rsync、VS Code 怎么共用这份配置
配置写好之后,所有基于 ssh 的工具都能直接受益。scp dev-box:/var/log/app.log . 会自动走 ProxyJump;rsync 需要的话写成 rsync -e ssh -av ./dist dev-box:/srv/app/,同样读取同一份配置;VS Code 的 Remote-SSH 扩展读取的也是 ~/.ssh/config,所以别名一次写好,编辑器里直接选择即可。
- 先在终端里用
ssh -v dev-box确认链路能通,注意看每一跳的认证日志。 - 确认 ControlPath 目录存在,第二次连接应该几乎瞬间完成。
- 在 VS Code 里通过 Remote-SSH 选择同一个别名,遇到卡在 Setting up SSH Host 时,对照Remote-SSH 跨境连接的两个独立故障点逐项排查。
- 需要观察每跳耗时时,用
ssh -vvv或在目标机上抓取连接时间戳,比凭感觉判断可靠。
当跳板本身位于跨境链路另一端,延迟和丢包会被每一次握手放大。这类场景下,开发机的出口线路稳定与否直接决定远程会话的体验,NasaCode 提供面向开发场景的稳定出口和独享 IP 选项,可以让跳板的白名单只放行固定地址;是否有改善,建议用上面的 ConnectTimeout 记录与 ssh -v 日志做前后对比。
小结
跳板配置的核心就三件事:用 ProxyJump 把多跳写成一行、用 ControlMaster 与 ControlPersist 复用连接、用 ConnectTimeout 与 ServerAlive 系列参数让故障快速暴露。配置完成后用 ssh -v 逐跳验证,再交给 scp、rsync 和编辑器复用。参数含义以你机器上 OpenSSH 版本的手册为准,升级后可以用 man ssh_config 再核对一遍。









