已吊销的 VPN 证书还能连上?检查 CRL 是否真正生效
当 CRL 从未到达验证方时,已吊销的证书仍然可以连接。请按顺序检查:签发者、已加载的序列号、重新加载行为,以及在线会话。
你吊销了证书,生成了新列表,但旧配置仍能建立隧道。吊销本身没有坏:CRL 是一份已签名的声明,说明某个序列号不再有效,而它只有在终止 TLS 的组件为正确的签发者加载它、并在做出接受决定之前生效,才会改变访问权限。大多数这类情况都出在这里,所以“吊销”和“拒绝”是两件不同的事实。
按顺序完成下面五项检查,并在第一项不成立处停下,因为后面的检查都假定前面的成立。
确认由哪个组件做出接受决定
指出验证客户端证书的进程,因为只有该进程才能执行列表。在 OpenVPN 服务器上,它是用 crl-verify 配置的守护进程本身。在 ocserv 中,它是 ocserv.conf 里的 crl 行。在 strongSwan 中,输入是已加载的 CRL 以及 strictcrlpolicy。VPN 前面终止 TLS 的代理或设备也可能是真正的验证方,如果是这样,它后面的守护进程根本看不到客户端证书。
WireGuard 属于另一类。它没有证书,也没有吊销列表;对等端靠配置中的公钥被接纳,因此终止访问意味着移除该密钥。如果你只在 WireGuard 部署里找 CRL,这个机制并不存在。
也要当心客户端侧的陷阱。因为不喜欢服务器证书而拒绝连接的客户端,是在执行服务器的证书链,而不是吊销自己的凭据。用户证书只在验证该用户证书的地方才会被吊销,而那几乎总是服务器侧。
确认列表是为哪个签发者签名的
CRL 只针对一个签发 CA。有根和中间 CA 时,叶子证书来自中间 CA,所以真正重要的列表是中间 CA 的 CRL;根的列表对这些叶子什么也没说。指向错误文件的验证方会欢快地解析它,找不到匹配条目,然后接受一切。
在动守护进程之前先确认配对。证书上的签发者必须与列表的 subject 一致:
openssl x509 -in client.crt -noout -issuer -serial
openssl crl -in intermediate.crl -noout -issuer -lastupdate -nextupdate当两者来自同一个 CA 时,为证书打印的序列号就是必须出现在列表里的值。如果它们不一致,你手里的是错误的 CRL 或它的错误副本。
有效性属于同一项检查。过去的 nextUpdate 会让列表过期,而以关闭方式失败的验证方会拒绝每个客户端,而不只是被吊销的那个。
确认序列号在守护进程加载的那份副本里
吊销会向 CA 数据库写入一条记录,重新生成会写入新文件。这两件事都到不了启动时加载旧副本的正在运行的守护进程。把列表导出来,查找该序列号:
openssl crl -in intermediate.crl -noout -text | grep -i -A2 'Serial Number'
openssl ca -revoke client.crt
openssl ca -gencrl -out intermediate.crl然后检查你的实现如何取得文件。OpenVPN 在启动时只读取一次传给 crl-verify 的路径,所以新列表需要重启或重启信号;同一个选项指向目录时会在每次连接时重新读取,目录模式正是为此存在。strongSwan 需要重新加载凭据,例如使用 swanctl --load-creds。磁盘上的文件正确,和验证方实际使用它,是两件不同的事实。
检查列表缺失或过期时的策略
这是许多部署从未明确做出的决定,而它决定了吊销是保护你,还是把所有人锁在外面。Fail-closed 意味着没有可用的吊销信息就拒绝;fail-open 意味着验证方在没有它的情况下继续。strongSwan 将这一选择暴露为 strictcrlpolicy。带 crl-verify 的 OpenVPN 会拒绝在无法读取或解析的文件上启动,而过期列表会表现为关于 CRL 过期的 TLS 验证错误,而不是静默接受。
| State of the revocation data | Fail-closed result | Fail-open result |
|---|---|---|
| List missing or unreadable | Verification fails, so expect an outage | Every client connects, including the revoked one |
List past nextUpdate | Validation errors until a fresh list is deployed | Old status is trusted indefinitely |
| Revoked serial present in the loaded list | Handshake rejected for that certificate | Handshake rejected for that certificate |
无论你选哪个方向,自动化比选择更重要:在 nextUpdate 之前重新生成 CRL 的任务,以及部署副本变旧时的告警,能避免任一策略演变成事故。用 OCSP 做在线检查把新鲜度转移给响应方,但同样的规则适用,因为未配置检查应答的验证方不会改变任何东西。
检查在线会话,然后检查密钥的副本
吊销在证书验证期间被评估,而这发生在连接时和重新协商时。已建立的会话会一直运行到重新协商,OpenVPN 的默认是用 reneg-sec 3600 每小时一次。如果这个人必须立刻离开网络,就要在发布列表的同时终止会话,然后确认重连被拒绝。
把凭据和它的副本分开。在一台笔记本上删除配置并不能阻止同一私钥的另一份副本通过认证;让每份副本失效的是吊销,而且只有前面的检查成立时才有效。给替换设备它自己的证书,这样一个可以被吊销而不影响另一个。
在宣布完成之前:验证组件已确定,列表的签发者与叶子的签发者一致,被吊销的序列号就在守护进程实际加载的副本里,缺失或过期列表的策略是有意为之并受到监控,在线会话是被终止而不是等它过期。这一切背后的格式在 RFC 5280 中规定。