吊销从不会伸进正在运行的隧道去删除会话。名单是证书校验的输入,只在开启 TLS 会话的控制通道交换中被查询。这一点同时解释了两种意外:被吊销的客户端能重新连上,是因为名单从未送达校验方;而已经建立的会话继续存活,是因为没有人重新校验任何东西。

名单是输入,不是动作

建立会话时,服务器会按自己的信任锚校验客户端证书,吊销指令则在这项判断中加一次名单查询。校验发生在服务器端,因此客户端看不到自己的证书已被吊销,仍继续提交同一份证书。所以,一个仍能连接的配置只能证明某个校验方接受了这条证书链,并不能证明吊销失败。

名单本身是一份带签发日期和下次更新日期的签名对象。一份不相关的名单、由另一机构签发的名单,或下次更新日期已过的名单,都不能替代当前名单;至于过期名单是被拒绝还是被悄悄接受,取决于部署方式。

新建连接与正在运行的会话

吊销只在会话建立或重新协商时评估,而不是对每个数据包的数据通道评估。已连上的客户端持有流量密钥,因此即使证书出现在名单上,它仍继续放行数据包。默认的重新协商间隔以小时计,所以更新后的名单可以对新来的连接生效,而已有的隧道照旧存活。

SituationWhat the list doesWhen it applies
Fresh connectionBlocks the handshakeAt verification, immediately
RenegotiationBlocks the new exchangeAt the next renegotiation interval
Established data channelNothingUntil the session ends

要立即生效,需要一次有意的操作,而不只是名单。重启服务会迫使每个客户端重连;通过管理接口终止单个会话则不会影响其他会话。每起事件二选一,并记录你用了哪一种。两种做法的影响范围不同,这才是真正的决定。

把校验方真正读取的文件送到位

名单必须由机构记录生成,然后复制到每一台校验证书的机器上。只在 CA 主机上生成、却从不装到服务器上,是最常见的故障,看起来完全像吊销功能坏了。

ca ca.crt
cert server.crt
key server.key
crl-verify /etc/openvpn/crl.pem

两个细节决定文件是否真的被读取。相对路径按配置目录解析,所以留在运维人员主目录里的副本可能永远找不到。而守护进程通常在启动后放弃特权,因此运行账号需要每个父目录的搜索权限,以及文件本身的读取权限。请用运行账号而不是 root 去验证这两点,否则测试证明的是错的东西。

在 systemd 主机上,加固过的单元也可能把路径藏起来,例如只读视图或受保护的系统目录。从服务内部看,这与文件缺失无法区分,所以在去找权限错误之前,先检查单元的限制。先读单元文件,再怪文件权限。

在服务器上确认,而不是在客户端上

服务器日志会说明发生了什么:打开名单、加载名单,或以被吊销的序列号校验失败。客户端只报一个笼统的握手失败,所以客户端日志不是查吊销决策的地方。

用被吊销的配置做一次全新尝试来验证,然后停下。这个配置能连上,是去检查文件路径和运行账号的信号,而不是假设名单错了的理由。把这次成功的尝试留作验收测试,不要把你没亲眼看到的重新连接算进去。

什么也不会吊销

从笔记本上删掉配置、从客户端移除证书文件,或者让用户别再连,都不会改变服务器上的任何东西。证书一直有效,直到机构记录吊销、校验方读到由此生成的名单。

这也是值得把这条链条写下来的原因:记录吊销,生成并签名名单,分发那一份确切的文件,并确认服务账号能读到它。每一环都很短,缺了任何一环,被吊销的客户端就会照旧开心地连上。四行的检查清单胜过一行都没有的假设。

相关文章