很多生产环境的机器不直接对外,要通过堡垒机(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-new 比 no 安全——只接受新主机;已存在 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清掉那条。
登录后参与评论。