4、自建CA与根证书:打造你的信任锚点
聊到mTLS,绕不开一个东西——CA。说白了,CA就是那个负责发身份证的机构。在公网场景里,你可以找Let's Encrypt、DigiCert这些商业CA。但在企业内部,尤其是微服务之间的mTLS通信,我强烈建议你自建CA。
为什么?因为根证书掌握在自己手里,你说了算。签发、吊销、续期,全流程可控。今天我们就来亲手搭建一个根CA。
4.1 根CA私钥:一切信任的起点
根CA私钥是整个PKI体系的命根子。它一旦泄露,你签发的所有证书都不再可信。所以,生成私钥这一步,必须认真对待。
我个人习惯用 openssl 来做这件事。命令很简单,但参数有讲究。
# 生成RSA 4096位私钥,使用AES-256加密
openssl genrsa -aes256 -out ca-key.pem 4096
这里我用了 -aes256,意味着私钥文件会被加密存储。每次使用私钥时,你都需要输入密码。嗯,这确实会麻烦一点,但安全系数高了一个档次。
我曾经见过一个团队,把根CA私钥密码写在便签纸上贴在显示器边框上……后来那个密码被保洁阿姨当垃圾扔了。建议用密码管理器保管,或者至少放在保险柜里。
生成后的私钥文件长这样:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,ABCD1234...
...(一堆Base64编码的内容)...
-----END RSA PRIVATE KEY-----
注意看文件头,有 ENCRYPTED 字样,说明私钥是加密的。如果你看到的是 BEGIN PRIVATE KEY 而没有加密标记,那就要小心了——私钥以明文存储,风险极高。
4.2 根自签名证书:信任链的顶端
有了私钥,接下来就是生成根证书。根证书是自签名的——也就是说,它自己证明自己可信。听起来有点循环论证,但这就是PKI的根基。
生成根证书的命令:
openssl req -x509 -new -nodes \
-key ca-key.pem \
-sha256 -days 3650 \
-out ca-cert.pem \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=My Root CA"
几个关键参数我解释一下:
- -x509:输出自签名证书格式
- -days 3650:有效期10年。根证书有效期一般设得长,5到10年都行
- -sha256:摘要算法。别用SHA-1了,那玩意儿已经不安全了
- -subj:证书主体信息。CN(Common Name)写个有辨识度的名字,比如"My Root CA"
根证书的CN其实没那么严格,但建议用英文,避免某些老旧系统对中文支持不好。我一般写成 "CompanyName Root CA 2025" 这种格式,方便识别。
生成的证书内容可以用这个命令查看:
openssl x509 -in ca-cert.pem -text -noout
你会看到证书的版本、序列号、签名算法、有效期、公钥信息等。其中 Issuer 和 Subject 字段是一样的——这就是自签名的特征。
4.3 CA策略文件:规矩得立好
光有私钥和证书还不够。你还需要一个策略文件,告诉OpenSSL:哪些证书能签,哪些不能签。这就像公司的规章制度,提前定好,避免后面乱套。
我常用的策略文件 ca.cnf 长这样:
[ ca ]
default_ca = CA_default
[ CA_default ]
# 数据库和序列号文件
database = index.txt
serial = serial
# 新证书存放目录
new_certs_dir = ./newcerts
# 默认策略
default_md = sha256
default_days = 365
preserve = no
# 策略匹配规则
policy = policy_loose
[ policy_loose ]
# 国家必须匹配
countryName = match
# 省份可选
stateOrProvinceName = optional
# 组织必须匹配
organizationName = match
# 组织单位可选
organizationalUnitName = optional
# 通用名称必须提供
commonName = supplied
# 邮箱可选
emailAddress = optional
这里有个关键点:match 表示必须和根证书一致,supplied 表示必须提供但可以不同,optional 表示可有可无。
我个人建议,在内部环境里用 policy_loose 这种宽松策略。为什么?因为微服务的证书CN往往是服务名,比如 service-a.internal,它和根证书的CN肯定不一样。如果用严格策略(policy_match),那所有签发的证书CN都得和根证书一样,这显然不合理。
在运行签发命令前,需要先创建几个文件:
mkdir -p ./newcerts
touch index.txt
echo 01 > serial
index.txt 是证书数据库,记录所有已签发证书的状态。serial 文件记录下一个证书的序列号。
4.4 根证书的保管:比金库还重要
根证书和私钥的保管,是整个mTLS体系中最重要的一环。我见过太多因为根证书管理不善导致的安全事故。
这里我总结了几条硬性规则:
| 保管对象 | 建议措施 | 绝对禁止 |
|---|---|---|
| 根CA私钥(加密后) | 离线存储,放在U盘或HSM中,锁入保险柜 | 放在CI/CD服务器上、上传到Git仓库 |
| 根CA私钥密码 | 密码管理器 + 纸质备份(分开存放) | 写在代码注释里、存在明文文件里 |
| 根证书(公钥部分) | 可以分发到所有需要验证的客户端 | 无所谓,公钥本来就是公开的 |
| CA策略文件 | 版本控制,记录变更历史 | 随意修改不通知团队 |
我曾经在一个客户现场,发现他们把根CA私钥直接放在Kubernetes的ConfigMap里。你想想看,ConfigMap默认是明文存储的,等于把保险柜钥匙挂在大门上。后来我帮他们重建了整个CA体系,折腾了两天。
还有一个容易被忽略的点:根证书的备份。私钥和证书至少要准备两份物理备份,放在不同地点。万一机房着火了,你还有另一份。
4.5 本章核心逻辑图
下面这张图展示了根CA的创建流程和信任关系:
从图中可以看到,根CA是整个信任链的锚点。所有下级证书的信任,最终都追溯到根证书。所以,根证书和私钥的保管,再怎么强调都不为过。
4.6 验证你的根CA
最后,验证一下你的根证书是否可用:
# 查看证书信息
openssl x509 -in ca-cert.pem -text -noout | grep -E "Subject:|Issuer:|Not Before|Not After"
# 验证自签名(自己验证自己)
openssl verify -CAfile ca-cert.pem ca-cert.pem
# 输出应该是:ca-cert.pem: OK
如果看到 OK,恭喜你,根CA已经搭建完成。接下来就可以用它来签发服务端和客户端证书了。
根CA搭建完成后,建议把私钥文件复制到离线存储设备上,然后从工作机器上彻底删除。日常签发证书时,使用中间CA来做,根CA只在需要签发中间CA时才上线。这样即使中间CA被攻破,根CA仍然是安全的。