首次通过 SSH 连接到一台新服务器时,几乎所有用户都会遇到那个令人纠结的提示:「The authenticity of host can't be established」,然后在 TOFU(Trust on First Use,首次信任)的驱动下输入「yes」。这种体验在少量服务器场景尚可接受,但当运维规模扩展到数十甚至上百台主机时,传统公钥认证的弊端便逐一显现:每台机器需要单独部署 authorized_keys、主机密钥变更引发的「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED」令人不安、员工离职后的密钥回收更是繁琐。SSH 证书正是为解决这些痛点而设计,它自 OpenSSH 5.4(2010 年 3 月)引入,机制远比 X.509 证书简单 —— 本质上仍是一对 SSH 密钥,只是附加了签名与有效期信息。
传统公钥认证的四大痛点
运维场景中,公钥认证的固有缺陷制约着效率与安全。首先是密钥分发的复杂度:每新增一个用户或每台新服务器,都需要将公钥复制到目标主机的 ~/.ssh/authorized_keys,这在动态环境中几乎是不可持续的操作。其次是 TOFU 机制 —— 首次连接时指纹被缓存到本地的 known_hosts 文件,后续主机密钥变更(例如系统重装)会触发刺耳的警告,用户往往不知所措。第三是密钥回收困难:员工离职后手动删除 authorized_keys 中的条目容易遗漏,形成隐蔽的安全风险。最后是主机密钥轮换的连锁反应 —— 重建服务器意味着所有客户端都需要重新确认主机指纹,这在大规模基础设施中是不可接受的。
SSH 证书的核心优势
SSH 证书通过引入认证机构(CA)的概念,一次签名即可打通整个基础设施。其核心优势体现在以下几个维度:
免部署 authorized_keys:用户公钥无需存在于目标服务器的 authorized_keys 文件中,CA 签发的证书天然被服务器信任。这意味着新员工入职时只需获取一张证书,即可访问所有授权机器。
自动过期机制:证书可设定明确的生命周期,例如 +1w(一周)、+24h(24 小时)、+52w(52 周)。过期后自动失效,无需手动撤销。需注意服务器与客户端时钟偏差可能导致验证失败,生产环境应启用 NTP 同步。
消除 TOFU 确认:客户端配置 @cert-authority 规则后,所有由该 CA 签发的主机证书自动被信任,首次连接不再弹出指纹确认对话框。
主机密钥轮换无感知:服务器重建时重新签发主机证书即可,客户端无需任何操作,因为信任关系建立在 CA 而非具体主机密钥上。
细粒度权限控制:签名时可指定 principals(-n 参数)限定可登录的用户名,支持 force-command(-O force-command)强制执行特定命令,支持 source-address 限制源 IP CIDR。例如 -O source-address=192.0.2.0/24 限定仅能从指定网段登录。
实施路径:五步构建 CA 体系
第一步:生成 CA 密钥对
CA 本质上是一个 ECDSA 或 ED25519 密钥对,建议使用 ECDSA 以获得更短的密钥长度,同时确保安全强度。创建专用目录并设置严格权限(umask 077):
umask 077; mkdir CA
ssh-keygen -t ecdsa -C "Production SSH CA" -f CA/ssh-ca
chmod -w CA/ssh-ca*
生成的 ssh-ca 为私钥(严格保管),ssh-ca.pub 为公钥(可分发至所有服务器)。
第二步:签署用户证书
用户将自己的公钥提交给 CA 管理员(或通过安全通道传递),管理员使用 CA 私钥签发证书。关键参数包括:-I(证书标识)、-n(允许登录的 principal,即用户名)、-z(序列号,用于审计)、-V(有效期):
ssh-keygen -s CA/ssh-ca -I "jane-jolie" -n jane -z 001 -V +1w jane.pub
生成的 jane-cert.pub 即为证书文件,使用时需与私钥 jane 放在同一目录:
ssh -i jane jane@server.example.com
若私钥设置了 passphrase,首次连接时 SSH 会提示输入,解密后的私钥可加入 ssh-agent 避免重复输入。查看证书详情:
ssh-keygen -L -f jane-cert.pub
输出显示证书类型、签发 CA、有效期、 principals 及扩展权限(如 permit-pty、permit-port-forwarding)。
第三步:签署主机证书
每台服务器的主机密钥也需要由 CA 签发。获取服务器的公钥(例如 ssh_host_ed25519_key.pub)后,使用 -h 参数签发主机证书:
ssh-keygen -h -s CA/ssh-ca -V +52w -I "server-001" -z 1000 -n server.example.com ssh_host_ed25519_key.pub
注意 -n 指定的 principal 应与客户端连接时使用的主机名或 IP 地址匹配。若需同时支持主机名和 IP 访问,可用逗号分隔: -n server.example.com,192.0.2.141。
第四步:服务器端配置
将 CA 公钥安装到服务器,并配置 sshd 信任该 CA:
install -m444 /path/to/ssh-ca.pub /etc/ssh/ssh-ca.pub
echo "TrustedUserCAKeys /etc/ssh/ssh-ca.pub" >> /etc/ssh/sshd_config
echo "HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub" >> /etc/ssh/sshd_config
sshd -t && systemctl restart sshd
重启后,sshd 将信任所有由该 CA 签发的用户证书,无需在用户的 authorized_keys 中添加任何内容。
第五步:客户端配置
客户端只需在 known_hosts 中添加一条 @cert-authority 规则,即可信任由该 CA 签发的所有主机:
echo "@cert-authority *.example.com $(cat CA/ssh-ca.pub)" > ~/.ssh/known_hosts
pattern 支持通配符(如 *.example.com)和逗号分隔的多个模式。此后连接任何匹配的主机都不会触发指纹确认,且主机密钥变更对用户透明。
高级约束与审计
强制命令与功能限制
签名时可嵌入强制性约束,限制用户行为。例如强制仅能执行 date 命令,即使客户端请求 uname 也会被替换:
ssh-keygen -s CA/ssh-ca -I "jane-jolie" -n jane -z 2 -V +1w -O force-command=/usr/bin/date jane.pub
清除所有默认扩展并显式启用部分功能:
ssh-keygen -U -s CA/ssh-ca -I "jane-jolie" -n jane,root -z 4 -V +1w \
-O clear \
-O extension:permit-agent-forwarding \
-O extension:permit-port-forwarding \
jane.pub
上述配置禁用了 PTY 分配,用户登录后无法获得交互式终端,但可使用端口转发功能。
源 IP 限制
限制证书仅能从特定网段使用:
ssh-keygen -s CA/ssh-ca -I "jane-jolie" -n jane -z 3 -V +1w -O source-address=192.0.2.0/24 jane.pub
不符合源地址的连接请求将被服务器拒绝并记录到日志。
审计与故障排查
服务器日志(auth.log 或 journalctl)记录了所有证书认证的详细信息,包括用户指纹、证书 ID、序列号、签发 CA 的指纹。典型日志条目:
sshd-session[3099]: Accepted publickey for jane from 192.0.2.42 port 17087 ssh2:
ECDSA-CERT SHA256:2WH263LauVfk5XvxHvrdvNt0y9OgaHBLSvcQ+R6u/KE
ID Jane Jolie (serial 1) CA ECDSA SHA256:A5ZBb5b/GbAv03EAb8fmDzv4p+q0g8Ulxrt8QZpbamM
常见错误排查:若连接时仍提示输入密码,检查服务器日志中是否出现「Certificate invalid: name is not a listed principal」—— 这表明证书的 -n 参数未包含目标用户名;若提示主机指纹确认,检查证书是否已过期(Certificate invalid: expired)或 known_hosts 中的 @cert-authority 规则是否正确。
参数速查清单
| 场景 | 关键参数 | 示例值 |
|---|---|---|
| 用户证书有效期 | -V | +1w(7 天)、+24h(24 小时) |
| 允许登录的用户 | -n | jane 或 jane,root(多用户逗号分隔) |
| 主机证书有效期 | -V | +52w(一年) |
| 主机 principal | -n | server.example.com,192.0.2.141 |
| 强制命令 | -O force-command=/path | -O force-command=/usr/bin/date |
| 源 IP 限制 | -O source-address=CIDR | -O source-address=192.0.2.0/24 |
| 禁用 PTY | -O clear | 先用 -O clear 清除默认扩展 |
局限性与适用场景
SSH 证书适用于管理员拥有 CA 私钥且对目标服务器拥有完全控制权的场景。对于共享主机或多租户环境,传统 authorized_keys 机制更为合适,因其不依赖 CA 密钥的分发与信任链管理。在自建基础设施中,采用证书体系可显著降低运维负担:新增用户只需签发证书,新增服务器只需部署 CA 公钥与主机证书,所有密钥生命周期由有效期自动管理,离职回收可通过过期机制无缝完成。
参考资料
- Jan-Piet Mens: SSH certificates: the better SSH experience
- Mozilla OpenSSH Guidelines: openssh
- IETF Draft: draft-miller-ssh-cert-06