证书与公钥基础设施(PKI)

说实话,很多人觉得PKI就是“CA签证书那套东西”。对,但也不全对。我在项目里见过不少团队,证书配了一堆,结果审计日志传输还是裸奔——不是TLS没配对,就是证书链断了。说白了,PKI是个信任模型,你得搞清楚你的审计日志该信谁。

PKI的两个核心角色

PKI里最重要的,就是“谁发证”和“谁用证”。我给你拆开聊。

CA(证书颁发机构) – 签发证书的权威方。我习惯称它为“信任起点”。
RA(注册机构) – 验证申请者身份,把请求转给CA。你想想看,CA要是自己验身份,效率太低了。

另一个角色是证书持有者(比如你的TLS服务端)。它拿私钥签名,公钥跟着证书曝光。审计日志客户端拿到证书后,沿着证书链往上追溯,直到找到自己信任的根CA。

嗯,这里要注意:证书链不能断。我在一个项目中排查日志告警,发现客户端报“无法验证证书”,查了半天——中间CA的证书没装到服务端上。断链了,信任就垮了。

X.509证书结构

现实中我们用得最多的就是X.509 v3证书。我摘几个关键字段,你配审计日志TLS时得盯着看:

字段含义配审计日志时要注意
Subject证书所有者(如服务器域名)必须与TLS端点域名完全匹配
Issuer签发者如果自签,Issuer = Subject
Validity生效与过期时间审计设备时钟不准?曾经有人栽在这上
Subject Key Identifier公钥标识做证书链追溯用的
Authority Key Identifier签发者公钥标识用来匹配父证书
Extended Key Usage用途扩展必须包含 serverAuth
小心时钟偏差 – 我曾经帮一个客户排查审计日志中断,发现所有设备证书都没问题,但客户端系统时间跑偏了4小时,导致TLS握手时证书“未生效”。解决方式:统一用NTP,别依赖人工设钟。

证书链验证流程

审计日志客户端收到服务端证书后,会做三件事:

  1. 检查有效期限 – 过期或未生效?直接拒。
  2. 验证签名 – 用父证书的公钥解签名,确保证书内容没被篡改。
  3. 追溯信任锚 – 顺着Issuer字段一层层找,直到本地信任的根证书。

这个流程,说白了就是“你朋友说你是真的,我信你朋友,但我得先确认你朋友是XX”。链断了或者中间证书没存本地,验证就过不了。

我习惯把根证书预装在审计日志客户端的信任存储里。中间证书由服务端在TLS握手时下发。你想想看,如果每个客户端都存几十个中间CA,运维会疯的。

自签名 vs 商业CA

审计日志场景里,两种方式我都用过:

方式优点缺点
自签名CA成本低、完全可控客户端要手动导入根证书,难批量
商业CA浏览器/系统默认信任年费不低,过期前续签容易忘
内部搭建私有CA(如OpenSSL)自由签发、链可控需要维护CRL/OCSP服务
我的建议 – 如果审计日志只在内部网络传输,自己搭一个私有CA就够了。运维上,用脚本自动化签发并推送客户端根证书,别用手动点网页。

生成一套自签证书(实战片段)

用OpenSSL搭建迷你PKI,我经常这样干:

# 1. 生成根CA私钥和证书
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 \
  -subj "/C=CN/O=AuditLab/CN=RootCA" -out rootCA.crt

# 2. 生成服务端私钥和证书请求
openssl genrsa -out server.key 2048
openssl req -new -key server.key -subj "/C=CN/O=AuditLab/CN=tls.audit.internal" -out server.csr

# 3. 用根CA签发
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key \
  -CAcreateserial -days 365 -sha256 -extfile ext.cnf -out server.crt

这里ext.cnf里要写上extendedKeyUsage = serverAuth,否则部分TLS库会拒。我遇到过客户端是Go版本,非要明确声明用途,不然握手失败。

SVG:PKI信任模型与证书链

下面这张图展示了审计日志场景下的信任链:从根CA出发,经过中间CA,到日志服务端证书,客户端正向验证。

PKI信任模型——审计日志证书链 根CA(自签) 中间CA(子CA) 服务端证书 审计日志客户端 签发 信任链验证方向 验证顺序 客户端拿到服务端证书 → 用中间CA公钥验签名 → 再追中间CA的签发者(根CA) 直到在本地信任存储中找到根证书,链闭合 → 握手成功

CRL与OCSP

证书一旦泄露或误发,需要第一时间吊销。审计日志场景下,我见过两种策略:

  • CRL(证书吊销列表) – 静态列表,客户端定期拉取。缺点:时效性差,列表可能很大。
  • OCSP(在线证书状态协议) – 实时查询。不过OCSP服务器如果是单点,挂了会影响握手。

我个人习惯:内部审计日志环境用CRL就够了,每天夜里拉一次。OCSP太麻烦,尤其是小团队没必要为了完美牺牲可用性。

千万别忘配吊销检查 – 我曾经见过一个审计系统,所有证书都配了,唯独客户端没启用CRL检查。结果黑客用泄露的证书加密数据流,审计日志照样正常跑。嗯,后来加了 openssl crl -verify 的校验环节才堵上。

实践检查清单

配完PKI,我建议你逐条过一遍:

  1. 根证书是否已经安装到所有审计日志客户端的信任存储?
  2. 服务端证书的Subject(CN或SAN)是否与连接的域名完全一致?
  3. 证书链文件是否在服务端配置中串联正确?(rootCACert + intermediateCert + serverCert,顺序别搞反)
  4. 客户端是否开启了证书验证?(不少日志库默认不验证,得显式打开)
  5. 有没有设置证书过期前30天的自动告警?

说实话,大部分“TLS传输失败”的问题,照着这个清单扫一遍就能定位。我调试过的项目里,80%出在第二条——域名没配SAN,或者SAN里写的是IP但证书签了域名。OpenSSL 1.1.1之后对IP兼容也不好,尽量用域名。