SSH 跳板机实战:用 SSH Config 与 ProxyJump 高效管理多台服务器

引言:多台服务器的管理之痛

做站长的年头长了,手里难免会有好几台服务器:一台跑博客,一台跑数据库,一台做备份,可能还有客户或朋友的机器要帮忙维护。机器一多,问题就来了:每台机器要记 IP、记用户名、记密钥文件,每天 ssh 来 ssh 去,命令又长又容易记错;更麻烦的是,很多机器出于安全考虑并不直接暴露公网,只能通过一台跳板机中转访问。如果你也在为这些事头疼,那么 SSH Config 和 ProxyJump 这两个东西就是为你准备的。本篇文章从最基础的跳板连接讲起,一步步带你配置出一套高效、安全的多服务器管理方案。

一、跳板机到底解决了什么问题

跳板机(Jump Host,也叫堡垒机)是一台位于公网、充当"中转站"的服务器。所有对内部服务器的访问都必须先连到跳板机,再由它转发到目标机器。这样做的好处显而易见:第一,内部服务器不需要暴露公网 IP,攻击者根本无法直接扫描到它们,攻击面大幅缩小;第二,所有访问都经过跳板机,便于集中审计,谁在什么时间访问了哪台机器、执行过什么操作,都能查到记录;第三,权限可以集中管理,员工离职或合作结束,只需要在跳板机上撤销一次权限即可。

很多云服务商(比如 AWS、腾讯云、阿里云)都提供托管的堡垒机服务,但对个人站长来说,自己拿一台低配小机器配置成跳板机就完全够用了,成本低且完全可控。

二、最原始的跳板方式:先跳再连

在没有 SSH Config 之前,访问一台只能通过跳板机到达的服务器,流程是这样的:先用 ssh 登录跳板机,然后在跳板机上再执行 ssh 登录目标机:

ssh root@192.168.1.100        # 第一步:登录跳板机
ssh appuser@10.0.0.5          # 第二步:在跳板机上登录内网目标机

这种方式的缺点很明显:第一,要手动输两次命令、输两次密码(或加载两次密钥),效率低;第二,密钥文件必须放到跳板机上,等于把私钥副本散落在中间机器上,存在安全隐患;第三,scp 传文件、git 拉代码这些操作会变得极其别扭,因为你要处理两级跳转。所以这种方式只适合应急,不适合日常使用。

三、SSH Config:给每台服务器起个好记的名字

SSH 客户端支持读取用户配置文件 ~/.ssh/config,在这个文件里你可以为每台服务器定义别名和连接参数,之后直接 ssh 别名 就能连接,不用再敲一长串命令。基础语法如下:

Host blog
    HostName 1.2.3.4
    User root
    Port 22
    IdentityFile ~/.ssh/id_ed25519_blog

Host db
    HostName 5.6.7.8
    User admin
    Port 22022
    IdentityFile ~/.ssh/id_ed25519_db

配置完成后,ssh blog 就等价于 ssh root@1.2.3.4 -i ~/.ssh/id_ed25519_blog,scp 文件、rsync 同步、git 远程操作也都可以直接用别名,比如 scp index.html blog:/var/www/html/。配置文件的生效规则是从上到下匹配第一个匹配的 Host 条目,所以通用的默认参数可以放在文件末尾的 Host * 段里,比如全局启用压缩、设置超时、禁止密码登录等。

还有一个小技巧:Host 支持通配符,比如用 Host *.internal 匹配所有内网机器,把共用的 User 和 Port 统一写在这段里,减少重复配置。

四、ProxyJump:一条命令直达目标机

SSH 7.3 开始提供了 ProxyJump 指令(对应命令行参数 -J),它把"经过跳板机连接目标机"这个动作封装成了 SSH 客户端原生的能力。配置非常简单,只需要在目标机的配置里加一行 ProxyJump:

Host internal-web
    HostName 10.0.0.5
    User appuser
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_app

Host bastion
    HostName 1.2.3.4
    User root
    IdentityFile ~/.ssh/id_ed25519

配置好之后,在本地执行 ssh internal-web,SSH 客户端会自动先连 bastion,再从 bastion 连到 10.0.0.5,全程只需要本地这一个进程,中间不需要你手动操作,也完全不需要在跳板机上存放任何私钥。ProxyJump 还支持多级跳转,用逗号分隔即可:

ProxyJump jump1,jump2

多级跳转适合网络层级比较深的企业环境,个人站长一般一级就够用了。命令行的等价写法是 ssh -J root@1.2.3.4 appuser@10.0.0.5,不写配置文件也能临时用。

五、ProxyJump 与 ProxyCommand 的区别

在 ProxyJump 出现之前,老玩家用的是 ProxyCommand 配合 nc 命令实现跳板:

Host internal-web
    HostName 10.0.0.5
    User appuser
    ProxyCommand ssh -W %h:%p bastion

ProxyCommand 的意思是:用括号里这条命令来代替直接的 TCP 连接,-W 参数让 ssh 充当一个纯转发的隧道。它和 ProxyJump 实现的效果几乎一样,但有几个实际差别。第一,ProxyJump 是 SSH 协议原生的实现,对 SSH 版本要求低、行为更稳定,而且支持跳板机密钥、代理、连接复用等配置的继承;ProxyCommand 依赖系统里有 nc 或者新版 ssh 的 -W 模式,可移植性稍差。第二,ProxyCommand 更灵活,理论上可以塞进去任意命令,比如走 HTTP 代理、做端口转发等特殊场景。对绝大多数人来说,优先用 ProxyJump,遇到特殊需求再考虑 ProxyCommand。

六、密钥转发与 ssh-agent 的正确用法

默认情况下,通过跳板机连接目标机时,本地私钥不会传给跳板机,这是对的,因为私钥一旦在中间机器上落地就有泄露风险。但有时候目标机只信任你本地这把密钥,你又不想把密钥文件拷到跳板机上,怎么办?答案是用 ssh-agent 和密钥转发(Agent Forwarding)。

原理是这样的:本地运行 ssh-agent 进程保管私钥;连接跳板机时开启 -A 参数(对应配置 ForwardAgent yes),跳板机上的 SSH 进程会把"验证密钥的请求"原样转发回本地,由本地 ssh-agent 完成签名,私钥本身始终不出本地。这样目标机看到的还是你本地的身份,但任何中间机器上都找不到私钥文件。

不过,密钥转发有一个必须牢记的安全警告:开启 ForwardAgent 之后,跳板机上的 root 用户(或者能读你 agent socket 的任何进程)都可以借用你的 agent 去连接其他信任这把密钥的机器,相当于把你的身份使用权交了出去。所以使用原则是:只在信任的跳板机上开启,用完立刻关闭,绝不全局开启。更安全的替代方案是只把目标机专用的密钥文件放到跳板机或本地不同位置,让每台机器各用各的密钥,即使一台泄露也不影响其他机器。

本地 ssh-agent 的日常用法是把密钥加入 agent 并设置超时:

eval "$(ssh-agent -s)"
ssh-add -t 3600 ~/.ssh/id_ed25519

ssh-add -t 3600 让密钥在 agent 里只存活一小时,超时自动移除,兼顾方便与安全。macOS 和主流 Linux 发行版大多会在登录时自动启动 ssh-agent,只需要把密钥加进去一次。

七、通过跳板机传文件:scp 与 rsync

配置好 ProxyJump 之后,传文件变得异常简单,scp 和 rsync 都支持 -J 参数或直接使用配置里的别名:

scp ./backup.tar.gz internal-web:/data/backups/
rsync -avz --progress ./site/ internal-web:/var/www/site/

rsync 是个人站长最该掌握的同步工具:第一次全量同步,之后只传差异部分,配合 --delete 参数还能让远端和本地保持完全一致,非常适合部署网站代码。一个常用的部署命令示例:

rsync -avz --delete -e "ssh -J bastion" ./dist/ appuser@10.0.0.5:/var/www/html/

如果只需要临时开一条隧道访问内网的服务,比如内网某台机器的管理后台只监听 127.0.0.1,可以用本地端口转发:ssh -L 8080:127.0.0.1:8080 internal-web,然后浏览器访问 localhost:8080 就能看到内网管理后台。反向场景(内网机器主动连出来)用 -R,动态代理用 -D,这三个参数是 SSH 隧道最常用的三件套。

八、真实场景配置模板

把上面的知识点串起来,一份适合个人站长的完整 ~/.ssh/config 长这样:

# 通用默认值
Host *
    ServerAliveInterval 30
    ServerAliveCountMax 3
    ConnectTimeout 10
    Compression yes
    AddKeysToAgent yes

# 跳板机
Host bastion
    HostName bastion.example.com
    User root
    Port 22
    IdentityFile ~/.ssh/id_ed25519_bastion

# 生产环境内网机器(经跳板机)
Host prod-web
    HostName 10.0.1.10
    User deploy
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_deploy

Host prod-db
    HostName 10.0.1.20
    User admin
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_deploy

# 测试环境
Host test-web
    HostName 10.0.2.10
    User deploy
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_deploy

ServerAliveInterval 30 的作用是每 30 秒发一个保活包,防止连接因为长时间空闲被中间网络设备掐断,对挂在跳板机后面的长连接尤其重要。AddKeysToAgent yes 会在首次使用某把密钥时自动把它加入 ssh-agent,省去手动 ssh-add 的步骤。

有了这份配置,日常操作就是 ssh prod-web 登录、rsync 部署、scp 备份,全部一条命令,不再需要记任何 IP 和长参数。配合 zsh 的补全功能,输入 ssh p 按 Tab 就能自动补全主机名,体验非常顺畅。

九、跳板机的安全加固

跳板机是整个体系的咽喉,它一旦被攻破,内网所有机器都暴露在攻击者面前,所以跳板机的安全加固怎么强调都不过分。以下几项是必须做的。

第一,禁用密码登录,只允许密钥认证。在 sshd_config 里设置 PasswordAuthentication no,并把 PermitRootLogin 设为 prohibit-password,杜绝暴力破解。第二,限制来源 IP:云安全组里只放行你常用的 IP 段,或者用 Match Address 指令限定能连跳板机的来源。第三,启用登录审计:把 sshd 的日志独立出来,或者用 auditd 记录登录和命令执行,配合日志异地备份,出事时才有据可查。第四,保持系统更新,跳板机上尽量少装不必要的软件,降低被利用的面。第五,如果有多人使用,给每个人单独的账号和密钥,不要共享 root 密码,密钥指纹要登记造册,方便回收权限。

有条件的话,还可以给跳板机开双因素认证(比如 Google Authenticator 或 TOTP),配合 pam 模块配置,登录时除了密钥还要动态验证码,安全性再上一个台阶。个人站长如果机器不多,这一条可以量力而行。

十、常见问题排查

用 ProxyJump 的过程中,最常遇到的几个问题和排查思路如下。

第一,连接报 Permission denied (publickey)。优先检查目标机的 IdentityFile 是否写对、目标机 authorized_keys 里是否有对应的公钥;如果目标机只信任某把密钥,确认本地 ssh-agent 里加载的就是那把。用 ssh -v internal-web 查看详细连接过程,会明确显示每一步用了哪个密钥、被哪台机器拒绝。

第二,报 "Could not resolve hostname"。通常是 ProxyJump 里引用的跳板机别名写错了,或者跳板机的 Host 块定义在目标机 Host 块的后面,SSH 解析时会找不到。把跳板机定义放在配置文件前面即可。

第三,连接建立后频繁断开。检查是否开启了 ServerAliveInterval,没开的话长连接很容易被 NAT 或防火墙静默掐断,配置里加上即可。

第四,内网机器互相通信正常,但本地连不上。先手动测试两段链路:ssh bastion 确认跳板机通,再在跳板机上 ssh 目标机确认内网通,分段定位问题出在哪一段。还要检查跳板机的 sshd 是否开启了 AllowTcpForwarding,默认是 yes,如果被关掉,ProxyJump 的转发会失败。

第五,报 "Too many authentication failures"。本地 ssh-agent 里挂了很多密钥,客户端逐个尝试超出了服务端限制。解决方法是给目标机的 Host 块显式指定 IdentityFile 和 IdentitiesOnly yes,只尝试指定的密钥。

总结

SSH Config 加 ProxyJump 是一套投入极小、回报极高的组合:配置一次,之后每天省下大量重复输入;跳板机集中管控,内网机器不暴露公网,安全性大幅提升;ssh-agent 密钥转发让私钥始终留在本地,兼顾灵活与安全。再加上 rsync 部署、端口转发隧道这两个延伸技能,个人站长管理几十台服务器也游刃有余。建议今天就打开你的 ~/.ssh/config,把常用机器整理进去,再用 ProxyJump 把内网机器接进来,你会立刻感受到效率的提升。

Last modification:August 28th, 2026 at 08:10 am

Leave a Comment