SSH CA 签名认证:告别 authorized_keys 分发地狱
一条命令,让所有服务器信任一个新员工——不需要配置 authorized_keys,不需要逐个 ssh-copy-id,不需要担心哪个机器漏了。
这就是 SSH CA 签名认证做的事。
如果你读过我上一篇关于 knockd 端口敲门的文章,应该已经感觉到我对 SSH 安全的态度:防线要薄,但要分层。knockd 是第一层(端口隐藏),CA 签名是第二层(密钥管理)。
这篇文章不讲「SSH 基本用法」,讲的是如何把 SSH 密钥管理从「每个机器各管各的」升级成「一个 CA 说了算」。
传统方式的病根
现在你是怎么管理 SSH 密钥的?
ssh-copy-id user@server1
ssh-copy-id user@server2
ssh-copy-id user@server3
...
小团队还行。当你有 20 台服务器、5 个员工、每人换一次电脑——你就已经记不清哪个 key 还活着、哪个机器漏了。
更致命的是离职回收:
- 找到离职员工的公钥指纹
- 登录每台服务器的
~/.ssh/authorized_keys - 一行一行找,删除
- 祈祷没有漏掉哪台
这个过程不止不安全,是必然出错——只要是人手操作的步骤,就一定会有机器被漏掉。
SSH CA 的工作原理
概念非常简单:
┌─────────────┐ 签 名 ┌──────────────┐
│ Server A │◄──── 可 信 ────────► │ CA Key Pair │
│ Server B │◄──── 可 信 ────────► │ (离线安全) │
│ Server C │◄──── 可 信 ────────► │ │
└─────────────┘ └──────┬───────┘
│
┌────────▼───────┐
│ User Key │
├────────────────┤
│ 签过名的公钥 │
│ (ssh-ed25519- │
│ cert.pub) │
└────────────────┘
CA 持有私钥,给用户的公钥签名。签名后的证书(cert)有效期可以设(比如 24 小时)。
服务器不存你的公钥,只存 CA 的公钥。服务器看到你出示的证书,检查是 CA 签的、有效期没过——放行。
加人:CA 签一声,员工拿着证书就能上所有机器。
踢人:等证书过期就行了。不用挨个删 authorized_keys。
紧急回收:搭配 RevokedKeys 文件,一条命令废掉一个证书。
搭建步骤
1. 创建 CA 密钥对(离线机器)
选择一个不上生产网的机器,或者一台专门做 CA 的离线机器。
ssh-keygen -t ed25519 -f ~/.ssh/ca_user_key -C "SSH CA User Key 2026"
ssh-keygen -t ed25519 -f ~/.ssh/ca_host_key -C "SSH CA Host Key 2026"
两条:一条签用户证书,一条签主机证书。分开管理,权限不同。
私钥必须加密,密码短语设强一点。不是开玩笑的——谁拿到 CA 私钥,谁就能伪造证书登录所有机器。
2. 把 CA 公钥部署到所有服务器
每台服务器的 /etc/ssh/sshd_config 加一行:
TrustedUserCAKeys /etc/ssh/ca_user_key.pub
然后把 ca_user_key.pub 拷贝到 /etc/ssh/ca_user_key.pub。
再在 /etc/ssh/sshd_config 里加上(可选但推荐):
RevokedKeys /etc/ssh/revoked_keys
重启 sshd:
sudo systemctl restart sshd
搞定。以后所有服务器的 authorized_keys 文件可以删掉。清空。一干二净。
3. 为客户签发证书
员工生成自己的密钥对(用 Ed25519):
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
把公钥 ~/.ssh/id_ed25519.pub 发给 CA 管理员(或者通过内部工具自助签发)。
CA 签发:
ssh-keygen -s ~/.ssh/ca_user_key \
-I "lihua@example.com" \
-n "lihua,root" \
-V "+52w" \
~/.ssh/id_ed25519.pub
参数解读:
-s:指定 CA 私钥-I:证书身份标识,用于日志审计-n:允许登录的用户名,逗号分隔-V:有效期,+52w是一年;推荐个人密钥给 30-90 天
输出文件:id_ed25519-cert.pub,这就是证书。
员工把这个证书放到 ~/.ssh/ 目录下(和密钥对一起),SSH 客户端会自动识别。
验证一下:
ssh -i ~/.ssh/id_ed25519 lihua@server1
如果没问题,应该直接登录成功,不会再提示输入密码。
4. 主机证书(可选——彻底消灭 known_hosts 警告)
每次连新服务器时 The authenticity of host ... can't be established 这个警告,所有人都见过。
主机证书解决这个问题。
首先,服务器也需要把自己的主机公钥交给 CA 签发:
ssh-keygen -s ~/.ssh/ca_host_key \
-I "server01.example.com" \
-h \
-V "+5y" \
/etc/ssh/ssh_host_ed25519_key.pub
-h 表示这是主机证书。生成的 ssh_host_ed25519_key-cert.pub 放到 /etc/ssh/ 下。
然后在 sshd_config 里加上:
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
重启 sshd。
客户端要做的是:在全局 ~/.ssh/known_hosts 或 /etc/ssh/ssh_known_hosts 中加一条:
@cert-authority *.example.com ssh-ed25519 AAAAC3... (CA 主机公钥)
以后连接 *.example.com 的任何服务器,自动验证主机证书由 CA 签发,不会再有警告。
日常管理:加人、踢人、轮换
加人:员工提交公钥 → CA 签发证书(设 90 天有效期)→ 员工拿到 cert → 直接登录。零服务器操作。
正常离职:等证书过期。员工拿到的证书有有效期,过期自然失去权限。不需要做任何操作。
紧急回收:在 /etc/ssh/revoked_keys 文件中写入证书序列号:
ssh-keygen -L -f ~/lihua-id_ed25519-cert.pub # 查看序列号
echo "serial: 1234" | sudo tee -a /etc/ssh/revoked_keys
一条命令推送到所有服务器(Ansible/ssh 循环),立即生效。
CA 私钥轮换:生成新 CA 密钥对→重新签发所有有效证书→更新每台服务器的 TrustedUserCAKeys。这个动作应该在设计时就自动化。
真实的坑
没有自动化工具的 SSH CA 是另一种噩梦
如果你手动 ssh 到 50 台服务器部署 TrustedUserCAKeys,那你只是换了一种痛苦的方式。SSH CA 必须配合 Ansible、Salt、或自建脚本做分发。CA 签发的自动化是收益最大化的前提。
证书有效期太短会被骂
设 7 天有效期很安全,但员工每周要找 CA 管理员续签。大部分团队折中在 30-90 天,配合用户自助签发工具(比如写个小 Web 页面 + 公司 SSO 认证)。
SSH 客户端版本
OpenSSH 5.4+ 支持 CA 功能(2010 年),Ubuntu 16.04+、CentOS 7+ 都内置支持。基本上不需要担心版本问题。但 Windows 自带的 OpenSSH 需要确认版本——Windows 10 1809+ 可以,更老的建议用 WSL。
不兼容遗留系统
有些堡垒机、跳板机、第三方工具不支持证书认证。需要单独给这些系统配置传统的密钥方式。
总结
SSH CA 签名认证做三件事:
- 统一信任中心:一台 CA 管所有服务器信任
- 时间绑定的权限:证书过期是天然回收机制
- 零配置新机器:新服务器部署时配好 TrustedUserCAKeys,之后证书级别的任何操作不需要碰它
如果用一句话说清楚:让 SSH 密钥管理从手工作坊变成工业化流水线。
配合 kncokd + SSH CA + fail2ban 三层,你的 SSH 防线已经超过大多数企业标准了。
原文发表于 cn-res.vip,没有版权自由转载。标明出处非常感谢,删了也没事。