契机
就在昨日(08月23日)晚上到今天凌晨,头脑发热的我在毫不理智的情况下升级了Infisical,导致之前一个非常简约的SSH CA功能彻底沦为企业级功能。虽然他们做了个类似 HashiCorp Boundary 的工具,带了完整的审计工具,但是配置起来实在是蛋疼不已。
比如,要接入 SSH PAM 你就需要先部署一个 Gateway,然而如果要部署 Gateway,你还得先部署一个 Relay。
前者的作用是完成资产注册和反向连接,后者只是方便你进入不好进入的网络(比如生产内网等),把Infisical和子网打通,感觉是真的越来越复杂了。
所以为了照顾自己本来就不大的脑容量,决定降级。又因为自己没有做数据库备份,所以只能从头来了(呜呜呜别骂了,咱已经把备份做上了
原理
考虑到自己管理的机器越来越多,每台机器都得上传自己key的公钥,管理和吊销都很麻烦。因此想到了直接用CA管理的方式。也一定程度上避免了自己私钥被窃,或者哪天没带key导致上不去机器的问题。
核心原理和PKI一样,CA给用户key和服务器key都做签名,用户信任Host CA,服务器信任User CA。

原理图也很简单:
- Linux服务器信任SSH证书授权机构(CA)通过SSH向服务器提供访问权
- SSH CA 是一个单一地点,用于配置多个 Linux 服务器的访问
- 客户端请求SSH CA访问Linux服务器,SSH CA决定该客户端是否被授权
- 如果客户端获得授权,会向客户端颁发一个的SSH证书,用于对Linux服务器的访问
- 可选的配置一个证书有效期,能保证证书定期过期、轮转。
CA给SSH客户端发放客户端证书,本质上就是在传统的ssh key基础上对公钥签名,把验证长期单个公私钥对的责任边界,交给CA验证是否有效即可。SSH客户端用私钥签名+证书向服务端握手,服务端验证这本证书是否为受信任的CA签发,且在有效期,还没被吊销。
最终,是就能连,不是就拒。
问题
原理了解清楚了,那么考虑一些问题:
-
客户端证书遗失怎么办?
解决思路有两个,一个是签发长期证书,然后塞到智能卡里(比如Yubikey),每次认证只需要插卡并触摸就能完成。另一种思路是走SSO方案,每次走SSO认证后给你一个临时证书,只能用几个小时这样(如果做额外实现的话,甚至可以单次失效,一次一密。但是考虑到网络稳定性和重连要重新认证导致的各种问题,过于麻烦,反而得不偿失)。
两种思路都能受到CA制约,所以即便是长期证书,也能做到按需吊销。
-
每次都拿一本证书,对客户端来说是不是配置地狱?
其实还好,如果你配合一些脚本用,可以做到把得到的证书和私钥,赛到ssh-agent里,这样完全避免了一大堆公私钥文件存放问题,权限问题等。
那么下面介绍一些常见方案。
方案
下面介绍到的方案,其实都可以加自己的一些支持,比如Root CA存到Yubikey或者自己的HSM/KMS里。
Infisical
因为是我自己的实践,我就先把这个放出来。
出厂会给你配置好一个User CA和一个Host CA,可以直接用也可以删了自己建立。

比如我的就设置成了这样(例图)。在公钥那边可以下载完整文件,把它传到所有机器的 /etc/ssh/infisical_ca.pub,接下来加两句话在sshd_config里就可以完成服务端的配置:
TrustedUserCAKeys /etc/ssh/infisical_ca.pub
PubkeyAcceptedKeyTypes=+ssh-rsa,[email protected]
对客户端来说,只需要信任Host CA就可以。
echo "@cert-authority HOST-A,HOST-B,* [HOST_PUB_KEY]" >> ~/.ssh/known_hosts
更多用法可以参见 sshd(8)