SSH config 写好 jump host 跳板(一行 ProxyJump 干掉所有手动 tunnel)

很多生产环境的机器不直接对外,要通过堡垒机(jump host)跳进去。
没配置 SSH config 时每次都要:

ssh -L 2222:internal:22 user@bastion
# 另开终端
ssh -p 2222 user@localhost

或者:

ssh -t user@bastion ssh user@internal

~/.ssh/config 里写好 ProxyJump,之后直接:

ssh internal     # 就完事了

最小可用 ~/.ssh/config

# 公开堡垒机
Host bastion
    HostName bastion.example.com
    User opsdude
    Port 22
    IdentityFile ~/.ssh/id_ed25519_company
    IdentitiesOnly yes

# 内网机器,通过 bastion 跳
Host db1
    HostName 10.0.0.11
    User dbadmin
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_company

Host app1 app2 app3
    HostName %h.internal.example.com
    User app
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_company

%h 是当前 Host 名字(app1 / app2 / app3)。整段不需要重复 3 遍。

之后:

ssh bastion          # 直接进堡垒
ssh db1              # 自动通过 bastion 进 db1
ssh app1             # 同上
scp file.tar app1:/tmp/    # scp / rsync 同样自动跳板
rsync -avz ./dist/ app1:/srv/myapp/

多层跳板

Host very-deep
    HostName 192.168.99.5
    User admin
    ProxyJump bastion,intermediate
    # 等价于:
    # bastion → intermediate → very-deep

常用配置项速查

Host name
    HostName actual.host         # 真实主机名 / IP
    User myname                  # 登录用户
    Port 22                      # 端口
    IdentityFile ~/.ssh/key      # 指定密钥
    IdentitiesOnly yes           # 只用上面这个 key,不用 ssh-agent 里的其它
    ProxyJump bastion            # 跳板
    ProxyCommand cmd %h %p       # 自定义代理命令(少用了,被 ProxyJump 替代)
    LocalForward 9000 localhost:9000   # ssh -L 等价
    RemoteForward 9001 localhost:80    # ssh -R 等价
    ServerAliveInterval 60       # 60 秒发一个 keepalive 心跳
    ServerAliveCountMax 3        # 3 次没回应就断
    ControlMaster auto           # 复用 TCP 连接
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m
    StrictHostKeyChecking accept-new
    UserKnownHostsFile ~/.ssh/known_hosts

关键技巧:ControlMaster 复用连接

Host *
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m

意思是:每个 (user, host, port) 组合的第一次 ssh 建立真实 TCP;
后续 ssh / scp / rsync / git 全部复用这个 TCP,
不再重新握手 / 不再输密码(如果原先要的话)。

效果:

  • 第一次 ssh server 慢一点
  • 第二次 / scp / rsync / git push 几乎瞬开

/tmp/ 可能不够安全(多用户系统),放 ~/.ssh/cm-... 私有。

跳板的端口转发

Host db-via-bastion
    HostName 10.0.0.11
    User dbadmin
    ProxyJump bastion
    LocalForward 5432 localhost:5432
ssh -fN db-via-bastion    # 后台开 tunnel
psql -h localhost -p 5432 -U user

-fN 表示后台 + 不开 shell,纯做 tunnel。

SSH agent + agent forwarding

跳到中间机后再要去第三跳,不想把 key 拷到中间机:

Host bastion
    ForwardAgent yes
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
ssh bastion
# 在 bastion 上 ssh other —— 用的是你本地的 key

agent forwarding 有 root 风险(堡垒机 root 能用你的 key),
所以 只对自己完全信任的机器开。生产堡垒机用 ProxyJump 替代,
不让 key 真的暴露给堡垒机。

别名 + 子目录配置

# ~/.ssh/config
Include ~/.ssh/config.d/*.conf
# ~/.ssh/config.d/work.conf
Host work-*
    User worker
    IdentityFile ~/.ssh/work_key

把不同项目 / 客户的配置拆开,避免单个文件几百行。

known_hosts + 自动接受新主机

在脚本里第一次连陌生机器:

ssh -o StrictHostKeyChecking=accept-new server

accept-newno 安全——只接受新主机;已存在 host key 改变了仍报错
(中间人攻击信号)。

密钥类型

# 推荐:Ed25519,短、快、安全
ssh-keygen -t ed25519 -C '[email protected]'

# 老兼容:RSA 4096
ssh-keygen -t rsa -b 4096

服务端要支持 Ed25519(OpenSSH 6.5+ / 2014 后基本都行)。

安全:禁用密码登录

服务端 /etc/ssh/sshd_config

PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
sudo systemctl reload ssh

之后任何密码登录都被拒;只能凭密钥。结合 fail2ban / 改端口效果叠加。

踩过的坑

  • IdentityFile 没设 IdentitiesOnly yes → ssh-agent 里的其它 key
    会被一一尝试,可能因连续失败把你 ban 了。配同事的 git host 时尤其
    容易踩。
  • ProxyJump 在很老的 OpenSSH(< 7.3)不支持,要用 ProxyCommand:
    ProxyCommand ssh -W %h:%p bastion
  • ControlPersist 时长不要无限("yes"),机器一直长连接,重启后状态
    乱。10m / 1h 比较合理。
  • known_hosts 里的旧 host key 在机器重装后失效,连接报 MITM 警告。
    ssh-keygen -R hostname 清掉那条。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。