你的 VPN 客户端提示证书无法验证,对话框就停在那里。文件在,服务器在运行,同样的配置文件上个月还能在另一台笔记本上用。在那一行告警底下,客户端其实把对端证书送过了四道关卡:你配置的证书颁发机构为签名路径背书、这条路径能走到该机构、对端名称正是你要求的那个、证书此刻可以用于这个用途。找到关上的那道门,修复往往只涉及一个文件;跳过这一步,你就要花一下午反复导入证书包。

先读对话框,再改配置文件

证书错误的措辞由底层库给出,而不是你安装的 VPN 产品,所以那串原文就是第一手证据。“无法获取本地颁发者证书”指向路径或信任锚。“证书已过期或尚未生效”指向时间。“不支持的证书用途”指向扩展密钥用法。名称不匹配会告诉你它想要哪个名字。这四类问题没有一个是靠重装客户端解决的。

动手之前先把日志级别调高。OpenVPN 在带 --verb 4 运行时会在握手附近报出验证失败,strongSwan 则把身份与链的判定写进 charon 日志。然后确认你检查的是哪一份证书,因为人们常常测的是磁盘上的文件,而配置文件里内嵌的是更旧的副本。当配置文件内嵌 PEM 块时,被测的就是内嵌的那份证书。

证书颁发机构签的是身份,不是权限

该机构持有一个名称和一把签名密钥。它按自己的策略签发证书,把公钥绑定到那个名称,并附带有效期与用途限制。你的客户端只需要机构的证书就能认出签发者;它从不需要签名密钥,而把密钥发给客户端,等于把签发任何部署所信任身份的能力交了出去。

信任一个机构,会让它签过的每张证书都成为候选,而不是正确的那一个。同一内部 CA 签发的 Web 服务器证书同样是候选。名称与用途两道关卡正因此存在,也正因如此,泄露的 CA 密钥比任何单台服务器都严重:它能波及该机构签发过的每一个身份。按设备分别签发客户端证书,这样丢一台笔记本只是一次吊销,而不是全站换钥。

把客户端正在尝试构建的路径重建出来

路径从对端证书出发,经过零个或多个中间证书,最终抵达你信任库里的某个根。缺少中间证书是最常见的链故障,而从客户端看,它与不受信任的根毫无区别。先读叶子证书,再让你打算下发的材料自己走一遍 OpenSSL 建链。

openssl x509 -in server.crt -noout -subject -issuer -dates
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt
openssl verify -show_chain -CAfile root.crt -untrusted intermediate.crt server.crt

退出状态为零,说明路径用这些文件建成了;失败时它会点名够不到的那张证书。如果 openssl verify 成功而客户端仍然拒绝,差别就在服务器实际发送了什么,或者配置文件加载了哪个信任文件。在 OpenVPN 里,中间证书可以随服务器证书文件一起下发,也可以用 --extra-certs 单独提供;而一个在同一个主体名称下塞了两个根的包,会把你的某台客户端送进错误的分支。

名称与用途是两道独立的关卡

建链从不询问名称是不是你的。只有配置文件设置 --verify-x509-name 时 OpenVPN 才会检查,而只比对通用名称的老习惯,会在身份放在 subjectAltName 里的证书上失效。IKEv2 部署会把配置的身份与 SAN 条目或可分辨名称比对,具体看客户端;而通配符或 %any 之类的值,会悄悄关掉你以为存在的那项比较。

接下来是时间与用途。时钟快了几个小时的笔记本,会拒绝尚未生效的证书;而过期的中间证书会让路径失败,哪怕叶子证书仍在有效期内。用途类失败来自扩展密钥用法里没有 serverAuth,或者 keyUsage 不允许握手签名,OpenSSL 会把这类情况报为不支持的证书用途。按正确的模板重新签发;这条消息里没有任何一条构成关闭验证的理由。

吊销只有在有人配置过之后才会运行

CRL 或 OCSP 响应不会被自动查询。在 OpenVPN 服务器上,只有在 --crl-verify 指向某份列表时,客户端证书才会与之比对。客户端一侧对服务器证书的检查取决于具体实现,而且往往并不存在。strongSwan 需要先启用吊销插件并配置策略,才会去查对端的 CRL。

这就解释了那张迟早会来的工单:已吊销的客户端证书照样能连上,于是所有人都断定吊销坏了。其实根本没有人检查。发布并刷新 CRL,或者把客户端证书做得足够短命,让过期的吊销只在一小段时间内重要;再趁没有出事的时候,用一张实验证书把吊销这条路演练一遍。

一套不让验证被关掉的修复顺序

先按症状分类再碰文件,因为表格里的每一行都会把你引向不同的对象。

Client saysMost likely gateFirst check
unable to get local issuer certificatetrust anchor or missing intermediateyour own openssl verify against the files the profile loads
expired or not yet validvalidity windowleaf and intermediate dates against the device clock
unsupported certificate purposeextended key usageserverAuth present, keyUsage allows the handshake
name mismatchpeer identitysubjectAltName entries versus the profile name

一次走完清单:确认配置文件加载的是哪个文件、自己把路径建一遍、检查服务器是否发送中间证书、比对时钟、读 SAN、读 EKU,然后重新连接,看着同一行日志消失。如果某台设备根本拿不到 CA,固定公钥指纹才是诚实的替代方案,因为 OpenVPN 2.6 接受 --peer-fingerprint,把信任收窄到一把密钥,而不是取消检查。这些字段各自的含义,可参考 RFC 5280。

相关文章