全球超过900万台服务器每天在用SSH,但97%的运维团队还在用2010年就该淘汰的钥匙管理方式。
这不是夸张。当你第50次给新员工批量添加公钥、第20次翻日志找离职员工的残留权限、第N次对着"Are you sure you want to continue connecting?"发呆时——OpenSSH 5.4版本(2010年3月)就内置的证书体系,正在角落里吃灰。
本文用一次完整的技术考古,还原这套被严重低估的基础设施。
01 钥匙管理的三重崩溃
传统SSH模型在"一个人三台服务器"的场景下优雅简洁。公钥丢进authorized_keys,私钥本地保管,连接时双向验证。
规模扩张后,这套模型开始系统性崩解。
第一重:分发灾难。每来一名开发,运维需要把他的公钥写入N台服务器的authorized_keys。N=50时是体力活,N=500时是自动化脚本,N=5000时没人知道哪些服务器还存着三年前的旧钥匙。
第二重:回收黑洞。员工离职时,HR发一封邮件给IT部门。但钥匙散落在哪些机器上?生产环境、测试集群、那台2019年部署的遗留数据库?没有中央登记册,只能靠人脑和grep命令碰运气。
第三重:信任幻觉。第一次连接新服务器时,SSH客户端抛出一串十六进制指纹,问你"确定要继续吗?"。你确定吗?你打电话给同事核对过吗?还是像99%的人一样直接敲了yes,把中间人攻击的风险埋进known_hosts?
这三件事每天都在发生。不是边缘案例,是核心痛点。
证书体系的设计者早就看穿了这一切。
02 证书如何重构信任链
理解SSH证书的最快方式:把它想象成TLS证书的精简版。
你不是给每台服务器分发1000把用户公钥,而是建立一个证书颁发机构(Certificate Authority,CA)——本质上就是一对特殊的SSH密钥。CA用私钥签发证书,公钥作为信任锚点预置在所有客户端。
验证流程被压缩成一步:客户端检查服务器出示的证书是否由可信CA签名。是,则放行;否,则拒绝。没有指纹核对,没有首次连接的信任建立,没有authorized_keys的爆炸式增长。
实际操作中需要两个CA,物理隔离。
用户CA(User CA)负责签发用户证书,证明"持有此证书的人被允许登录哪些服务器"。主机CA(Host CA)负责签发主机证书,证明"这台服务器的身份真实有效"。
分离的意图很直白:如果用户CA私钥泄露,攻击者只能伪造用户身份,无法冒充服务器诱导中间人攻击。反之亦然。爆炸半径被锁死在单一维度。
生成CA密钥的命令平淡无奇,但后果重大:
# 用户CA——这是你组织里最敏感的私钥之一
ssh-keygen -t ed25519 -f user_ca -C "user-ca@yourorg"
# 主机CA——同样级别保护
ssh-keygen -t ed25519 -f host_ca -C "host-ca@yourorg"
这两行命令输出的私钥文件,应该进入硬件安全模块(HSM)或至少离线存储。它们的权限位、备份策略、访问审计,需要对标根TLS CA的管控标准。
03 主机证书的部署实战
假设你已经有一台运行中的生产服务器,主机密钥对早已生成。证书化的第一步:用主机CA的私钥对现有公钥签名。
ssh-keygen -s host_ca \
-I "webserver-prod-01" \
-h \
-n "webserver-prod-01.example.com,10.0.1.50" \
-V +52w \
/etc/ssh/ssh_host_ed25519_key.pub
参数拆解:-s指定签名私钥,-I是证书标识(会出现在审计日志里),-h声明这是主机证书而非用户证书,-n列出证书适用的主机名和IP,-V设置有效期(这里是52周)。
输出文件是ssh_host_ed25519_key-cert.pub,与原公钥同名但多了-cert后缀。把它拷回服务器,在sshd_config里加一行:
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
重启sshd。这台服务器现在向所有连接者出示密码学签名过的身份证明,而不是裸奔的公钥指纹。
客户端侧的配置更简洁。把主机CA的公钥写进known_hosts,但用特殊语法:
@cert-authority *.example.com ssh-ed25519 AAAA...your-host-ca-public-key...
@cert-authority指令告诉SSH:对于匹配*.example.com的任何主机,信任由其签发的证书。首次连接时,客户端验证证书签名而非询问用户,中间人攻击的窗口被彻底关闭。
04 用户证书:权限的精细化雕刻
主机证书解决了"服务器是谁"的问题,用户证书解决"谁能进来、能做什么"。
生成用户证书的过程与主机证书对称,但多了权限控制的维度。
ssh-keygen -s user_ca \
-I "alice@example.com" \
-n "alice,webadmin,dbreadonly" \
-V +1w \
-z 1 \
alice.pub
关键在-n参数。这里列出的"alice,webadmin,dbreadonly"叫principals(主体标识),是SSH证书最核心的设计之一。
服务器端的sshd_config可以针对principals做细粒度授权:
Match Principals "webadmin"
AllowUsers alice bob carol
ForceCommand /usr/bin/audit-shell
或者更常见的:直接用principals映射到系统账户。
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
文件/etc/ssh/auth_principals/root里写一行"emergency-oncall",持有对应证书的人就能以root身份登录——不需要在服务器上预置他的公钥,不需要知道他明天会不会离职。
证书有效期是另一道保险。上面例子里的-V +1w意味着证书一周后自动失效。短期证书+自动化签发流水线,是现代零信任架构在SSH层的落地形态。
05 为什么15年过去还是小众
技术方案在2010年就成熟了,生态停滞在文档和工具链。
OpenSSH的证书实现是完整的,但周边基础设施几乎空白。没有Let's Encrypt式的免费CA,没有主流云厂商的托管服务,没有Terraform/Ansible的原生模块(直到近年才改善)。
更深层的原因是心智模型冲突。TLS证书的普及得益于浏览器的强制推行——地址栏挂锁不给就报警。SSH没有UI层,没有视觉反馈,证书的优势(消除首次连接警告)对用户不可见,只减轻运维负担。
而运维团队的迁移成本是真实的:现有authorized_keys的审计清理、CA密钥的 ceremonies(生成仪式)、证书签发流程的自动化、监控告警的重建。在"能用就别动"的基础设施文化里,这优先级天然靠后。
但变化正在发生。
HashiCorp Vault、Teleport、Smallstep等工具把SSH证书纳入零信任产品矩阵。GitHub在2021年宣布支持SSH证书签名提交。AWS、GCP的托管服务开始原生集成主机证书。
技术债务的偿还周期,往往以安全事件的频率为节拍器。
当你的团队下次面对"紧急撤销某员工所有服务器权限"的工单时,是准备grep 500台机器的authorized_keys,还是检查CA吊销列表后重新签发一批证书?
热门跟贴