VPN 客户端在信任证书之前会检查什么
把一条证书告警依次过一遍客户端的四道关卡:CA 信任、证书链构建、对端名称与用途,以及吊销策略。
你的 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 says | Most likely gate | First check |
|---|---|---|
| unable to get local issuer certificate | trust anchor or missing intermediate | your own openssl verify against the files the profile loads |
| expired or not yet valid | validity window | leaf and intermediate dates against the device clock |
| unsupported certificate purpose | extended key usage | serverAuth present, keyUsage allows the handshake |
| name mismatch | peer identity | subjectAltName entries versus the profile name |
一次走完清单:确认配置文件加载的是哪个文件、自己把路径建一遍、检查服务器是否发送中间证书、比对时钟、读 SAN、读 EKU,然后重新连接,看着同一行日志消失。如果某台设备根本拿不到 CA,固定公钥指纹才是诚实的替代方案,因为 OpenVPN 2.6 接受 --peer-fingerprint,把信任收窄到一把密钥,而不是取消检查。这些字段各自的含义,可参考 RFC 5280。