SSH 密钥管理实践: 个人学习笔记
运维中常见的场景是: 某台服务器上留下了离职同事的公钥, 或者一把私钥在十几台机器之间传来传去。问题不是"有没有用密钥", 而是密钥被谁掌握、能否追溯。
一、密钥的粒度: 一人一钥, 一用途一钥
最省事的做法是多人共用一把私钥,最危险的做法也是它:一旦泄露,无法定位来源,只能全量换钥。
推荐的粒度:
- 每个人至少一把个人密钥, 与身份绑定
- 生产环境跳板与开发环境使用不同密钥
- 自动化任务使用独立的服务账号密钥, 不复用个人密钥
二、算法与长度
| 算法 | 建议 | 备注 |
|---|---|---|
| Ed25519 | 首选 | 更短、更快, 现代 OpenSSH 均支持 |
| RSA | 兼容用 | 长度不低于 3072 位 |
| ECDSA | 谨慎 | 曲线参数选择不当会带来风险 |
| DSA | 禁用 | 已不安全 |
生成一把 Ed25519 密钥:
ssh-keygen -t ed25519 -a 100 -C "zhangsan@example.com" -f ~/.ssh/id_ed25519_prod
-a 100 提高 KDF 迭代次数, 增加口令暴力破解的成本。
三、私钥必须带口令, 且口令不写在命令行里
免口令私钥的便利性, 换来的是"文件被复制即等于身份被冒用"。
正确的做法是私钥加口令 + ssh-agent 缓存:
eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_prod # macOS
ssh-add ~/.ssh/id_ed25519_prod # Linux / Git Bash
四、服务器侧: 收紧 authorized_keys
公钥不是简单粘贴就完事, 加上限制项才能把风险收敛:
from="10.20.0.0/16",no-agent-forwarding,no-port-forwarding,command="/opt/backup/run.sh" ssh-ed25519 AAAAC3Nza... ops-backup@example.com
from=限定来源网段no-port-forwarding禁止把服务器当作跳板command=把服务账号锁死在指定脚本
五、轮换与回收
密钥不是"设好就不动"的资产。建议:
- 个人密钥 12 个月轮换一次, 关键系统 6 个月
- 离职流程中把"回收密钥"作为与"关闭账号"同等级的检查项
- 每季度扫描一次
authorized_keys, 找出无主条目
# 扫描所有服务器的公钥指纹, 输出用于比对的清单
while read -r host; do
echo "== $host"
ssh -o BatchMode=yes "$host" 'find / -name authorized_keys -exec ssh-keygen -lf {} \;' 2>/dev/null
done < hosts.txt
注意
不要用
ssh-keyscan 的输出作为主机身份校验依据 —— 它无法防御中间人攻击。首次连接请核对服务器指纹。六、把规范变成默认配置
写在笔记里容易忘,写进配置里才会生效。个人实践方式:
- 用 Xshell 的会话模板统一认证方式与算法偏好
- 用密码管理器统一保管私钥, 要用的时候再取出来, 别让它长期躺在桌面文件夹里
- 用
sshd_config的Match段落对关键主机施加更严格的策略
# /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
做到这一步, “谁在什么时候用哪把密钥登录了哪台机器"就有了明确答案 —— 这既是安全要求, 也是排障时最有用的信息。