authorized_keys 复制粘贴的时代该结束了
如果你管过三台以上的服务器,一定体会过这种痛苦:新加一台机器,得把公钥从这台复制到那台;某个同事离职,得登录所有服务器把他的公钥从 authorized_keys 里一行行删掉;想给所有服务器做一次密钥轮换,那简直是一场噩梦,漏掉一台就是安全隐患。
更麻烦的是主机密钥:每次重装服务器系统,客户端都会弹出一句吓人的 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!,你得手动 ssh-keygen -R 再重新 yes。这些问题的根源,是传统 SSH 用"每台机器一把钥匙"的点对点信任模型——机器一多,known_hosts 和 authorized_keys 就成了一团乱麻。
SSH 证书(SSH Certificate Authority)正是为规模化运维设计的:用一个 CA 给所有主机和用户签发证书,客户端和服务器只需要信任这一个 CA。签发、吊销、过期全在一处管理。这篇文章把整套流程走一遍。
核心概念:主机证书 vs 用户证书
SSH 证书分两类,别搞混:
- 主机证书(Host Certificate):CA 给每台服务器的主机密钥签名。客户端连接时,服务器出示主机证书,客户端只要验证"这是不是我们 CA 签的"就行,彻底告别人肉核对指纹。
- 用户证书(User Certificate):CA 给每个用户的公钥签名。用户登录时出示用户证书,服务器验证签名 + 检查证书里的 principals(允许登录的用户名)和有效期,不用再维护 authorized_keys。
两者用一个 CA 即可,也可以分两个 CA(生产上更推荐分开,权限隔离更清晰)。下面用同一个 CA 演示,你按需拆分。
第一步:生成 CA 密钥对
CA 私钥是整个体系的命脉,绝对不能放在任何一台业务服务器上。建议离线保存,或者放在你本地的管理机 + 加密磁盘里。生成命令:
ssh-keygen -t ed25519 -f ~/.ssh/ca -C "SSH CA for example.com"
# 会生成 ca(私钥,800 权限)和 ca.pub(公钥)强烈建议给私钥设一个 passphrase。CA 私钥一旦泄露,攻击者可以给自己签发任意用户/主机证书,等于拿到了你所有服务器的钥匙。设了 passphrase 后,签发时需要输入,正好形成一道人工确认。
第二步:给服务器签发主机证书
在 CA 管理机上,把各服务器已有的主机公钥(通常是 /etc/ssh/ssh_host_ed25519_key.pub)收集过来,逐个签发。签主机证书用 -h 参数:
# 语法:ssh-keygen -s CA私钥 -I 证书标识 -h -n 主机名列表 -V 有效期 主机公钥
ssh-keygen -s ~/.ssh/ca \
-I "web01-host-cert" \
-h \
-n web01.example.com,web01,10.0.0.11 \
-V +52w \
~/collected/web01_host.pub关键参数解释:
-I:证书标识(Key ID),会写进日志,方便审计"谁在哪台机器上登录了"。用有意义的名字。-h:签主机证书,不能漏。-n:principals,对主机证书来说就是该主机被认可的所有名字(域名、短名、IP)。客户端用它连接时,出示的名字必须在列表里,否则验证失败。-V +52w:有效期 52 周。主机证书有效期可以长一点。
生成的文件叫 web01_host-cert.pub,把它和主机私钥放到服务器的 /etc/ssh/ 下,然后在服务器 /etc/ssh/sshd_config 里告诉 sshd 用这个证书:
HostKey /etc/ssh/ssh_host_ed25519_key
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub重启 sshd 后,服务器出示的就是 CA 签过的主机证书了。
第三步:客户端信任 CA,告别 known_hosts 手改
在你的电脑上,把 CA 公钥配置成一个已知的信任源。编辑 ~/.ssh/known_hosts 或新增 ~/.ssh/known_hosts.d/ 文件,加一行(注意 @cert-authority 前缀):
@cert-authority *.example.com,10.0.0.* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... ca@example.com这一行的意思是:"任何主机名匹配 *.example.com 的服务器,只要出示的是这个 CA 签的主机证书,就无条件信任。"从此以后:
- 新服务器上线,签个证书就能连,不用再
yes确认。 - 服务器重装系统换主机密钥,只要重新签一张证书,客户端不会再报指纹变化。
- 有人做中间人攻击拿不到 CA 私钥就签不了证书,直接连不上,安全性反而更高。
第四步:签发用户证书,取代 authorized_keys
给每个运维/开发人员签发用户证书。语法和主机证书类似,但不带 -h,且 -n 这里是允许登录的用户名(principals):
ssh-keygen -s ~/.ssh/ca \
-I "alice@2026Q4" \
-n root,deploy \
-O clear \
-V +8h \
~/users/alice.pub注意这里 -V +8h——用户证书有效期设得很短(8 小时到几天),这是 SSH 证书的强大之处:过期类吊销。证书到期自动失效,不需要你去每台服务器删公钥。配合短周期签发,安全边界非常清晰。
-O clear 会清掉默认带上的一堆扩展选项。常用的还有:
-O force-command='/usr/local/bin/backup.sh':限制该证书只能执行某个命令(做自动化脚本专用凭证时特别有用)。-O source-address=10.0.0.0/24:限制只能从指定网段登录。-O no-port-forwarding:禁止端口转发。
用户公钥证书生成后是 alice-cert.pub,用户把它和私钥放一起,SSH 登录时会自动出示。
第五步:服务器端信任 CA,收口 authorized_keys
在每台服务器上,把 CA 公钥放到一个受控路径(比如 /etc/ssh/ca.pub),然后在 sshd_config 里声明信任:
TrustedUserCAKeys /etc/ssh/ca.pub
# 可选:给所有通过证书登录的用户加统一限制
AuthorizedPrincipalsFile /etc/ssh/principals/%u文件权限要严格:chmod 644 /etc/ssh/ca.pub && chown root:root /etc/ssh/ca.pub。配置好重启 sshd,如果证书里 -n 的 principals 包含 root,那么 ssh root@server 且带着有效证书就能直接进——服务器上根本不需要任何 authorized_keys 条目。
这时你可以把所有旧的 authorized_keys 清空,从此新增/删除人员只需在 CA 端操作,不用登录任何一台服务器。
证书的吊销与审计
SSH 证书的吊销不像 TLS 那么方便,主要靠两条路:
- 短有效期:这是主力方案。用户证书给 8 小时,就算泄露了,窗口也很小。别贪图方便签一年。
- RevokedKeys:在 sshd_config 里配置
RevokedKeys /etc/ssh/revoked_keys,把要吊销的公钥列进去。适合主机证书这类长有效期的场景。
审计方面,证书的 -I 标识会出现在服务器的 auth 日志里。用 ssh-keygen -L -f 证书文件 可以随时查看一张证书的全部信息(有效期、principals、扩展项),排查"为什么这个用户登不上"时非常有用:
ssh-keygen -L -f alice-cert.pub
# Type: ssh-ed25519-cert-v01@openssh.com user certificate
# Key ID: alice@2026Q4
# Valid: from 2026-10-04T09:00 to 2026-10-04T17:00
# Principals: root, deploy个人站长要不要上 SSH 证书
说实话,如果你只有一两台 VPS、一个人维护,传统 authorized_keys + known_hosts 完全够用,上证书体系纯属给自己加复杂度。但只要你符合下面任意一条,SSH 证书就值得投入半天时间搭起来:
- 服务器超过 3 台,主机密钥管理开始让你烦躁;
- 有多个团队成员需要登录,且人员有流动;
- 需要精细的登录审计(谁、什么时候、从哪登录);
- 有自动化脚本需要受限凭证(配合 force-command 和 source-address)。
搭好之后你会发现,日常运维的心态完全变了——加机器、删人员、轮换凭证,都变成 CA 端一条命令的事,而不是登录 N 台服务器挨个改文件。这种"可撤销、可审计、有有效期"的信任模型,才是规模化运维该有的样子。