SSH 跳板机(Jump Host)实战:一行命令直达内网
前言
公司内网服务器越来越多,研发、测试、生产环境各一套,全都躲在 NAT 后面。
以前的做法是:
# 先 SSH 到跳板机
ssh -p 2222 ops@103.25.xx.xx
# 再从跳板机 SSH 到内网
ssh ops@10.88.3.25
两台机器之间来回切,还要记住两套密钥,时间长了烦得一批。
后来发现 SSH 自带的 -J(ProxyJump)参数,一行命令直达内网,再也不用在跳板机上开端口转发,也不用手动二次 SSH。
环境拓扑
你(办公网) 跳板机(公网) 内网服务器
│ │ │
│ 不能直连内网 │ 103.25.xx.xx │ 10.88.3.25
│ ─────────────────────→ │ 作为跳板 │ 目标服务器
│ │ ─────────────────────────→ │
│ │ │
│ ◄───────────────────────────────────────────────────── │
│ 一行命令直达,中间过程 SSH 自动处理 │
机器信息(虚拟 IP)
| 角色 | IP | 说明 |
|---|---|---|
| 办公机 | 192.168.1.100 | 你的电脑 |
| 跳板机 | 103.25.xx.xx | 有公网 IP,充当入口网关 |
| 内网服务器 A | 10.88.3.25 | 研发环境 |
| 内网服务器 B | 10.88.4.10 | 测试环境 |
| 内网服务器 C | 10.88.5.88 | 生产环境 |
基础用法
一行命令直达
# 最简写法
ssh -J ops@103.25.xx.xx ops@10.88.3.25
# 如果跳板机和目标机端口都不是 22
ssh -J ops@103.25.xx.xx:2222 ops@10.88.4.10:2222
传文件(SCP)
scp -J ops@103.25.xx.xx ops@10.88.3.25:/data/backup.sql ./backup.sql
挂载远程目录(SSHFS)
sshfs -o ProxyJump=ops@103.25.xx.xx ops@10.88.5.88:/data/logs /mnt/prod-logs
进阶:配置文件管理
每次敲一长串 IP 和用户太反人类,写到 ~/.ssh/config 一劳永逸。
SSH Config 配置
# ~/.ssh/config
# ===== 跳板机 =====
Host bastion
HostName 103.25.xx.xx
User ops
Port 2222
IdentityFile ~/.ssh/id_rsa_bastion
ServerAliveInterval 60
# ===== 内网服务器 =====
Host dev-server
HostName 10.88.3.25
User ops
Port 22
IdentityFile ~/.ssh/id_rsa_internal
ProxyJump bastion
Host test-server
HostName 10.88.4.10
User ops
Port 2222
IdentityFile ~/.ssh/id_rsa_internal
ProxyJump bastion
Host prod-server
HostName 10.88.5.88
User admin
Port 22
IdentityFile ~/.ssh/id_rsa_prod
ProxyJump bastion
有了 config 之后
# 直达内网,不用记 IP
ssh dev-server
ssh test-server
ssh prod-server
# 传文件
scp dev-server:/data/backup.sql ./backup.sql
# 挂载目录
sshfs prod-server:/data/logs /mnt/prod-logs
# 配置里已经把 ProxyJump 写死了,不需要每次 -J
常用技巧
1. 多层跳板
# 三层跳板
ssh -J bastion,internal-jump,db-jump prod-db
2. 自定义端口跳板
ssh -J ops@103.25.xx.xx:2222 ops@10.88.3.25:2222
3. 多台机器同时连(跳板机只用一次)
# 配合 tmux + ssh config,同时连 3 台服务器
tmux new-window "ssh dev-server"
tmux split-window "ssh test-server"
tmux split-window "ssh prod-server"
4. 免密:把密钥加到 ssh-agent
# 一次性添加,当前会话内免密码
ssh-add ~/.ssh/id_rsa_bastion
ssh-add ~/.ssh/id_rsa_internal
ssh-add ~/.ssh/id_rsa_prod
# 然后所有 ssh/scp/sshfs 操作都不用输密码
5. 不想配 config?给命令起别名也行
# ~/.bashrc
alias ssh-dev='ssh -J ops@103.25.xx.xx ops@10.88.3.25'
alias ssh-test='ssh -J ops@103.25.xx.xx ops@10.88.4.10'
alias ssh-prod='ssh -J ops@103.25.xx.xx admin@10.88.5.88'
对比:端口转发 vs Jump Host
| 端口转发 | Jump Host | |
|---|---|---|
| 配置复杂度 | 每台机器要加规则 | 一行命令搞定 |
| 安全性 | 端口暴露在外网 | 只暴露跳板机一个入口 |
| 维护成本 | 新增机器要改 NAT 规则 | 加一条 config 就行 |
| 原生支持 | SSH 基础功能 | SSH 7.3+ 自带 |
| 传文件 | SCP 也要转发 | 直接 -J 参数 |
| 多人协作 | 每人要配置各自的转发 | 共享跳板机即可 |
注意事项
1. 目标机的 HostName 填的是「从跳板机看到的 IP」
不是公网 IP,是内网 IP(10.x.x.x / 172.x.x.x / 192.168.x.x)
2. SSH 版本要求 >= 7.3
ssh -V 查看,7.3 以下的用 -o ProxyCommand 代替
3. 跳板机本身要做好安全加固
- 禁止密码登录,只允许密钥
- 限制来源 IP
- 开启审计日志
4. 密钥链太长可以用 ssh-agent 转发
ssh -A -J bastion dev-server
(谨慎使用 -A,会暴露你的 agent socket)
后记
以前我在 Proxmox 上跑了一堆虚拟机,全躲在 NAT 后面。给每个 VM 配端口转发规则,维护起来头大。
自从用上 ssh -J,配置一次 ~/.ssh/config 之后,连内网机器就跟连本地一样自然。跳板机还是那个跳板机,但你再也不需要记住它的端口号了。
如果你还在手动 SSH 到跳板机再 SSH 到目标机,赶紧试试 -J 参数——少敲一次 SSH,多喝一口茶。