两种 VPN 故障在用户眼里一模一样,却需要相反的修复。名称不匹配说明证书本身有效,但签发给了别的对象;过期错误说明证书此刻无效。两者都不是密码问题,而重置凭据是这两种情形下最常见的一小时浪费。动手之前,先读清楚失败发生在哪个阶段。

错误文本就是诊断结论

即使提示很短,客户端也会告诉你哪一项检查失败。不匹配会写出它期望的主机名和实际找到的名字;过期错误会提到有效期日期或时间。这两句话指向证书的不同部分。

在它出现的阶段去读。握手阶段的失败是证书问题;隧道建立之后的失败是路由或凭据问题。保留阶段信息,才能让排查不至于滑向无关的设置。

如果失败在多次尝试之间变化,还有第三种可能:同一个名字背后不止一个节点。

名称检查:客户端在比什么

客户端把配置中期望的身份与证书里的名字作比较,这些名字位于 subjectAltName 扩展中。配置文件里写原始 IP、证书未列出的别名,或者只是个恰好解析到同一台服务器的名字,都会在这一项检查上失败。能连到正确的机器,并不等于出示了正确的身份。

要检查服务器实际出示的证书,而不是上一次尝试留下的文件。下面的命令请求的就是你配置的那个名字,所以答案里包含真实客户端会看到的证书。

openssl s_client -connect vpn.example.com:443 -servername vpn.example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -dates -ext subjectAltName

受信任签发者签发的证书,仍然可能是给别的服务用的。请保持客户端的名称检查开启,因为信任某个 CA 并不等于授权由它签过的每一个名字。关掉检查,会把配置错误变成一次暴露。

过期:读的是谁的时钟

有效期是一对时间戳,验证方拿它们跟自己的时钟比较。时钟不准的设备会把有效证书报成已过期或尚未生效,此时该修的是时钟而不是证书。时区显示上的差异,与底层时间错误并不是一回事。

在下结论之前,先在客户端上把证书日期与 UTC 对照:

openssl x509 -in cert.pem -noout -dates
date -u

如果日期确实已经过去,就通过签发者续期。如果替代证书已经存在但尚未生效,按受支持的切换流程来做,而不是把时钟调过去迁就它。为了让证书通过而把设备日期往回拨,是一个后果远超隧道的决定。

为什么修好一个会暴露另一个

校验会依次执行一系列检查,第一个失败就终止了报告。把名字修好,客户端接下来可能会告诉你证书链不完整,或者证书已过期。这并不说明第一项检查是多余的,而是说这条链上不止一个问题;所以要预期第二个错误,而不要把它读成第一次修复错了的证据。

多个节点会让情况更糟。负载均衡的服务可能由不同成员出示不同证书,所以一个两次通过、一次失败的测试,反映的是整个集群而不是你的客户端。请把对端地址和尝试时间一并留在诊断记录里。

正是这个细节,把时好时坏的工单变成可复现的工单。

用一条新连接来验证

修复之后,开一条新连接而不是复用旧连接,确认原先失败的那个阶段现在能通过。然后再确认隧道确实在承载流量,因为握手成功并不等于路由可用。

把确切的失败阶段和证书细节随工单一起留档。

正是这份记录,能阻止下一个人因为证书问题去重置账户密码。身份与有效期是两个独立的问题,而 RFC 5280 是评估后者的参考标准。

相关文章