Hotdry.

Article

OpenSSH 证书颁发机构实战:PKI 工作流与密钥生命周期管理

基于 OpenSSH 证书颁发机构构建 PKI 工作流,实现 SSH 密钥自动过期撤销与无密码认证的工程实践,涵盖 CA 密钥管理、证书期限策略与 SSH_CONFIG 集成。

2026-04-03systems

在规模化服务器运维场景中,传统基于公钥分发的 SSH 认证方式面临密钥管理难题:每新增一个运维人员需要将公钥手动同步到所有服务器,人员离职后的密钥撤销更是需要逐台清理。OpenSSH 6.5 引入的证书机制提供了一种替代方案 —— 通过引入证书颁发机构(Certificate Authority,CA)的概念,将密钥分发问题转化为证书签发与信任传播问题。本文将聚焦 OpenSSH 证书的工程化落地,涵盖 CA 密钥管理、证书期限策略与客户端配置。

证书机制的核心原理

OpenSSH 证书与传统 X.509 证书的核心区别在于其简化设计:证书本身包含公钥、有效期、主体名称(principals)以及 CA 签名。客户端连接时,服务器只需验证证书是否由受信任的 CA 签署且在有效期内,即可完成认证,无需在服务器上预存用户公钥。

一个典型的 SSH 证书签发流程如下:首先使用 ssh-keygen -t ed25519 -f ca-user 生成 CA 密钥对,其中私钥 ca-user 必须妥善保管,公钥 ca-user.pub 分发到所有 SSH 服务器。接着,当需要为用户 Alice 签发证书时,执行 ssh-keygen -s ca-user -I "alice-admin" -n alice -V +52w alice.pub,该命令使用 CA 私钥对 Alice 的公钥进行签名,生成证书文件 alice-cert.pub。证书中的 -n alice 指定了允许登录的用户名(principal),-V +52w 表示证书有效期为 52 周。服务器端只需在 sshd_config 中配置 TrustedUserCAKeys /etc/ssh/ca-user.pub,即可信任所有由该 CA 签发的证书。

CA 密钥的分层管理策略

生产环境中,CA 密钥的安全性直接决定整个认证体系的可信度。最佳实践建议将用户证书 CA 与主机证书 CA 分离,使用独立的密钥对分别签发用户证书和服务器主机证书。这种分离设计可以限制单一 CA 密钥泄露的影响范围 —— 即使用户 CA 泄露,攻击者也无法伪造服务器主机证书实施中间人攻击。

CA 私钥应当被视为最高敏感级别资产。在密钥存储层面,推荐将 CA 私钥加密存储并离线保管,仅在需要签发证书时接入签名服务器。具体的工程做法是:将 CA 私钥存储在加密 USB 设备或硬件安全模块(HSM)中,签发流程在物理隔离的专用主机上执行。对于中小规模团队,也可以采用更务实的方案:使用 ssh-keygen -o -a 100 -o膜strong KDF 参数增强私钥的 passphrase 保护,并将私钥文件权限设置为 600,仅限少数管理员知悉密钥口令。

证书签发权限应当与日常运维权限分离。建议建立独立的证书签发工作流:由普通运维人员提交证书申请,管理员审批后由专用签发系统或脚本执行 ssh-keygen -s 命令。整个签发过程应纳入审计日志,记录签发时间、证书主体、有效期限及操作人员。

服务器端配置与 principal 约束

在 SSH 服务器端,核心配置项为 TrustedUserCAKeys,用于指定存放 CA 公钥的文件路径。该文件的格式为纯文本,每行一个 CA 公钥,支持配置多个 CA 以实现密钥轮换或多 CA 并行工作。以下是典型的服务器端配置示例:

# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca-user.pub

配置完成后,执行 sshd -t 验证配置语法,然后 systemctl reload sshd 加载新配置。需要注意的是,CA 公钥文件必须包含有效的 OpenSSH 格式公钥,权限应设为 644(对所有用户可读),避免 SSH 服务因权限错误而拒绝加载。

对于主机证书,服务器端需要配置 HostCertificate 指向本机已签发的主机证书,客户端则通过 TrustedHostCAKeys 信任主机 CA。主机证书的 principal 约束通常为服务器的主机名或 IP 地址,例如 -n server1,10.0.0.5。客户端首次连接时验证主机证书的签名与 principal,握手成功后会将主机密钥指纹缓存到 ~/.ssh/known_hosts 的证书格式条目中,后续连接直接验证证书有效性。

证书生命周期与撤销策略

SSH 证书的核心优势在于自动过期机制。与传统公钥不同,证书包含明确的生效时间与失效时间,失效后的证书自动失效,无需逐台服务器执行撤销操作。在实际部署中,建议根据安全等级设定不同的证书有效期:临时访问证书有效期设置为数小时至数天,长期运维证书设置为数周至数月,CI/CD 自动化流程使用的证书可设置为数小时并配合自动续期。

对于需要立即撤销的场景,OpenSSH 提供密钥撤销列表(Key Revocation List,KRL)机制。管理员可通过 ssh-keygen -k -f /etc/ssh/revoked_keys -s ca-user.pub -z 1 alice-cert.pub 将指定证书序列号加入 KRL,随后在服务器端配置 RevokedKeys /etc/ssh/revoked_keys。KRL 支持增量更新,可以高效处理批量撤销场景。需要注意的是,KRL 文件更新后需要执行 systemctl reload sshd 生效,且服务器不会主动拉取更新,需要配合配置管理工具或定期任务推送更新。

在监控与审计层面,建议在签发服务器上记录所有证书签发事件,包括请求主体、签发时间、证书序列号及有效期。同时在 SSH 服务器端启用 LogLevel VERBOSE,审计登录日志中是否包含证书认证的 principal 与密钥 ID,便于事后追踪与异常检测。

客户端集成与无密码认证

客户端使用证书认证同样简单。获得 CA 签发的用户证书后,将证书文件与私钥一同存放于 ~/.ssh/ 目录。假设私钥为 id_ed25519、证书为 id_ed25519-cert.pub(OpenSSH 自动识别同名 cert 文件),即可直接使用 ssh user@server 无密码登录。如果证书文件采用非默认命名,需要在 ~/.ssh/config 中显式指定 IdentityFileCertificateFile

对于需要跨机器使用同一证书的场景,可以配置 SSH 代理(ssh-agent)加载私钥与证书。Linux/macOS 系统可通过 ssh-add ~/.ssh/id_ed25519 将私钥加入代理,后续 SSH 连接时自动使用已加载的证书。Windows 环境下,Windows OpenSSH Client 原生支持证书文件,Pageant(PuTTY Agent)则需要将私钥与证书分别加载。

在持续交付场景中,证书的短期特性恰好契合自动化需求。构建脚本可在每次部署时请求短期证书,部署完成后证书自动失效,即使证书泄露也难以被长期利用。这种设计将密钥管理的重心从「保管」转向「流转」,通过缩短生命周期降低泄露风险。

工程落地的关键参数

综合以上实践,落地 SSH 证书体系的关键参数清单如下:CA 密钥采用 ed25519rsa -b 4096 算法,用户证书有效期推荐 +26w+52w,主机证书有效期推荐 +52w104w,短期临时证书设置为 +1h+24h。principal 配置应遵循最小权限原则,仅包含必要的用户名或角色标识。CA 公钥通过配置管理工具(如 Ansible、Chef)同步至所有服务器,确保密钥轮换时能够批量更新。

对于已有大量静态公钥的企业,渐进式迁移策略更为实用:先在不敏感环境验证证书机制,逐步将新用户引导至证书认证,同时保留传统公钥作为回退方案。迁移过程中可通过 AuthorizedKeysFileTrustedUserCAKeys 共存实现无缝过渡。


资料来源:OpenSSH 证书配置最佳实践参考了 scheibling.se 的 OpenSSH Certificates 配置指南以及 jadaptive 的 SSH 密钥管理实践;TrustedUserCAKeys 配置示例来源于 GitHub Gist 上由 allthingsclowd 维护的配置指南。

systems