OpenVPN tls-crypt-v2:客户端密钥与包装 blob 各自负责什么
tls-crypt-v2 配置文件包含客户端控制密钥和只有服务器能打开的包装副本。请把每个对象和每个停用步骤分开管理。
把 tls-crypt-v2 配置文件贴进工单看似无害,直到你数清文件里到底有什么。客户端的控制通道密钥旁边还有同一密钥的加密副本,而第三个对象——包装密钥——永远不离开接收它的服务器。这三者回答的是保管、共享和停用三个不同问题。把它们分开,多数策略争论还没开始就结束了。
配置文件里到底有什么
tls-crypt-v2 的客户端一半由一把密钥和它的包装副本组成。客户端用明文密钥保护控制通道,并在建立连接时把包装副本交给服务器,于是服务器能还原同一把密钥,而不必为每个客户端保存一份明文副本。包装密钥让这种还原成为可能,并且只属于接收方。下面的一切都取决于这三个对象各自放在哪里。
| Object | Where it lives | What can open it | What a leak costs |
|---|---|---|---|
| Server wrapping key | accepting servers only | the unwrap step inside the server | every wrapped copy issued to that group becomes readable |
| Wrapped client key | inside the client profile | the server wrapping key | it names a client and exposes its metadata, but not the key inside |
| Client control key | inside the client profile, usable as-is | the client that owns it | someone can open handshakes as that client until the server refuses the key |
按保管方式而不是按名称读这张表,后果自然显现。丢失包装密钥是代价高昂的事件,因为配置文件里没有任何东西能重建它,而诚实的补救是重新签发整个组。配置文件泄露更便宜却常见得多,因为人们把配置文件贴进工单时相信包装副本让文件可以安全共享。两类失败需要不同应对,这正是要把对象分开的原因。
为什么包装副本不是全部
配置文件同时携带可用的客户端材料和它的包装对应物,所以保护给服务器的那份副本,并不等于保护整个文件。blob 适合传输,不适合公开。其中的元数据对任何收到 blob 的人可见,包括后来读到那张工单的人。
把配置文件当作凭据而不是配置样例。泄露的文件让持有者拥有可用的客户端身份,直到服务器不再接受该身份,而包装对此毫无作用。每个客户端只签发一份配置,让撤销始终是单文件决定;包装密钥的备份要与它启用的服务器配置分开存放。这两种习惯都不能修复已被泄露的配置,但都决定了下一份配置多久能被控制住。
验证钩子位于握手的哪一步
验证钩子在 TLS 栈暴露之前运行,其职责是检查包装 blob 中携带的元数据。它拿到这些元数据以及一个小的、有文档说明的环境,可用的材料比认证钩子少。以为它能看见用户名、会话状态或插件变量,是这类钩子写坏的常见方式。请读该钩子自己的手册章节,而不是借用别的钩子的预期。
退出状态就是决定:非零结果拒绝客户端,零结果让握手继续。因此策略必须说明元数据缺失、无法解析或出现意外时怎么办。先写拒绝路径,再决定哪些值可以接受。
tls-crypt-v2 /etc/openvpn/server/tcv2-server.key
tls-crypt-v2-verify /etc/openvpn/server/verify-client-metadata.sh这两行就是服务器上的策略面:一行指定包装密钥,另一行指定判断每个客户端的程序。真正有意思的东西都在脚本里,它值得版本控制,也值得和其他访问规则一样的审查。
账户、证书和控制密钥分别停用
控制通道的提前接受不是认证,因为它发生在 TLS 身份检查之前,也发生在任何账户授权之前。停用账户、吊销证书、拒绝客户端控制密钥是三种机制下的三个动作。只做其中之一的部署留下的是缺口而不是策略。要有意把三者对齐,并记录哪一步行使哪一种权限。
时间点是第二层区别。改动后的接受列表只对新握手生效,已经建立的会话会继续运行,直到有东西终止它们。把新列表里的条目当作旧会话已结束的证据,正是被移除的客户端还能连上数小时的原因。
未对齐的权限会留下两个在实践中很容易发现的漏洞。账户可以已停用,而它的控制密钥仍能打开握手;证书可以已吊销,而元数据策略仍接纳同一个客户端。这两者是不同位置上的同一个错误,因为操作者把一份列表当成了全部权限。移除时把三份列表并排放,错误就暴露出来。
签发与撤销配置
签发是容易的一半:在接收方生成客户端密钥,把配置交给唯一一个所有者,限制包装材料的存放,并在每台接收服务器上运行同一个验证程序。便宜接纳是整个组的属性,不是最新主机的属性。第二台服务器如果脚本更旧或更松,就会悄悄成为部署中最弱的一环。
撤销需要按刻意安排的三步走。在验证钩子里拒绝该客户端,让新握手失败;如使用 PKI,吊销它的证书;停用账户,让后续授权无物可授。然后终止旧接受所允许的会话,因为它们不会察觉上述任何一步。在你承受得起弄坏的客户端上演练这个顺序。
配置里的元数据是那套策略的输入,不是访问控制已经存在的证据。OpenVPN 2.6 设计文档描述这些对象以及它们划定的边界,而强制执行仍然属于操作者。