4 min read

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,多喝一口茶