你在重新生成 CRL 之后立刻出现连接被拒绝,于是 CRL 看起来可疑。其实不是。拒绝是传输层的答复,证书校验发生在之后,位于隧道握手内部。时间上的巧合只是背景,不是证据。

两项检查能在一分钟内区分这两种情况,而且都不涉及信任设置。

在产生错误的那一层读错误

来自 connect 的 ECONNREFUSED 意味着传输尝试被拒绝:有东西以 reset 回应,或者协议栈报告端口不可达。证书问题不会产生这个错误,因为没有传输连接,TLS 握手根本不会开始。如果看到拒绝,客户端根本还没走到出示证书那一步。仅凭这一点就能排除吊销作为原因。

反过来也成立。被吊销的证书会完成 TCP 连接,然后握手失败,并在服务器日志中记为校验错误。

TCP 拒绝:没有人在监听

对 TCP,检查目标实例是否在运行,并绑定到配置文件中的地址和端口。ss -lntp 会显示监听者,而没有监听通常就是答案。防火墙若选择拒绝而非丢弃,也会产生同样的客户端消息,所以要两者都查。

地址族也要检查。只绑定 127.0.0.1 或只绑定 IPv6 的服务,会拒绝解析到另一族的客户端。

随后去读服务日志,而不是猜。CA 维护后重启可能因文件不可读或缺失而失败,永远进不到监听状态,日志会点出那个文件。那是启动失败,与证书被拒绝是另一类缺陷。

UDP 没有可拒绝的握手

基于 UDP 的 OpenVPN 不建立 TCP 意义上的连接,因此 connect 时没有东西可拒绝。在 Linux 上,UDP 套接字报出的错误可能来自先前数据报生成的 ICMP port-unreachable。udp(7) 手册页描述了这种异步行为。

这就是为什么 UDP 客户端在服务器进程运行、却未绑定到预期地址时,仍可能打印拒绝。

CRL 实际在哪里被检查

CRL 是在 TLS 握手期间、对端出示证书之后才被查询的,而且只有当服务器配置启用它时才会。OpenVPN 的 crl-verify 选项指向该文件,失败会以点出证书名的校验错误出现在服务器日志里。

因此被吊销的客户端在传输层能够连上,随后在认证阶段失败。同一台服务器、同一个端口,消息完全不同。

走到那一步时,检查 CRL 的签发者和有效期。由错误 CA 签发的 CRL,或在客户端连接前就已过期的 CRL,会产生与客户端自身证书毫无关系的校验失败。

下一次的简短运行手册

先确认传输:有监听者、地址族正确、防火墙没有拒绝。然后读启动日志,确认服务进入了监听状态。之后,也只有之后,再去看握手错误中的校验消息。让这个顺序保持固定,因为每一步都排除掉一整类原因。

记下传输方式、解析出的目标地址、端口和确切的错误文本。重装客户端会毁掉这些证据,而且通常什么也改变不了。

相关文章