tls-auth 的 key-direction:0 与 1 必须相反,不能相同
使用 tls-auth 时两端需要相反的 0 与 1,或者双方都省略该设置。相同的数字会失败,而 tls-crypt 从不使用它。
隧道的一端用另一个端从不检查的密钥槽来签名控制通道,连接在交换任何一张证书之前就以认证错误断开。这就是 tls-auth 方向不匹配的样子,而且它是确定性的:同样的两个文件每次尝试都失败,换任何网络都一样。日志里不会出现你要找的那个选项名,于是人们重建从未损坏的密钥、重新签发证书。解决办法是让两端互补,或者让两端都保持双向,而不是削弱验证。
故障发生在证书之前
使用 tls-auth 时,两端持有同一把共享密钥,各自使用由它派生出的两个槽之一:一个槽签发出站控制包,另一个验证入站控制包。方向 0 与方向 1 以相反顺序分配这两个角色,因此这一对必须互补,HMAC 校验才能对上。当一侧的分配被反过来,接收方就会在错误的槽里找签名并丢弃数据包。会话到此结束,所以这个错误关乎数据包认证,而不是证书库会产生的任何东西。
这种确定性对诊断很重要,因为时间或路径问题留下的痕迹不同:间歇性断连、只有一个方向失败,或只在特定网络下断开的会话。方向不匹配每次都在第一次握手时失败,而且在持有同样两个文件的另一台机器上失败得一模一样。用 --verb 4 读日志,去找第一个被拒绝的数据包,而不是最后一行。如果那次拒绝发生在任何证书交换之前,那么共享密钥及其方向就是值得检查的两件事。
| What you see | What it rules out | Next check |
|---|---|---|
| Authentication error before any certificate is sent | The data channel is irrelevant; the control channel never authenticated | Compare tls-auth and its direction on both ends |
| Certificate or handshake failure after the control channel authenticates | The shared key and its direction already agree | Check the CA, the certificate dates and the hostname |
| Session completes but throughput or cipher warnings appear | Direction was never the problem | Compare the data-channel cipher settings |
| Startup stops on an options error | The number itself is not the issue | Re-read the inline versus external directive syntax |
数字住在哪里
OpenVPN 2.6 手册 记录了两个位置:密钥单独成文件时用 tls-auth 的第二个参数,密钥内联在配置里时用独立的 key-direction 行。两者设置的是同一个值,所以配置应当二选一,绝不要同时使用。省略也是一种选择,它让两端进入双向安排,在双方都不指定方向时可用。两个携带相同数字的对端并不处于这种安排:各自都期望在一个槽里签名、在另一个槽里验证,结果两边都朝同一个方向做。
# server.conf, external key tls-auth ta.key 0 # client.ovpn, external key tls-auth ta.key 1 # client.ovpn, inline key key-direction 1
内联形式是独立一行的指令,不是密钥块开始标签上的属性;给那个标签加参数是错误,不是改方向。位置同样重要:指令写在它所属的块之外,写在块内的值会被当作密钥材料读取。照抄配置分发者本来的安排,不要自创配对,因为对一台服务器可用的配置,在另一侧可能已经镜像过了。
这个选项不碰什么
它不加密应用流量。tls-auth 只是在控制通道的数据包外面加一层 HMAC,数据通道由握手中协商的会话密钥保护,所以吞吐量或加密算法的问题与方向数字无关。这个设置也不增加第二层加密,正是这个误解让人去找更长的密钥。
它不适用于 tls-crypt,那是另一种控制通道机制,有自己的选项和密钥处理方式,也完全不涉及任何一端的证书身份。因此方向匹配只能证明两端对如何认证控制通道达成一致,并不能证明信任链已被验证。
把这一对齐,然后重连
在改动任何一侧之前先比较两份配置,因为去改本来正确的那一侧会让工作量翻倍。下面的 grep 显示每个文件选了哪种机制;详细运行显示控制通道到底有没有通过认证。两份输出都留着,下一次改动才能和已知状态对比。
grep -n -E 'tls-auth|tls-crypt|key-direction' server.conf client.ovpn openvpn --config client.ovpn --verb 4 2>&1 | grep -i -E 'hmac|tls error|control channel'
任何改动之后都要重启两端,因为这些选项在启动时只读一次,只重载一侧会让这对在整个旧会话期间都不一致。如果当前部署没有配置方向也能工作,那么给一端加上这个设置就会重现你最初的故障;要么都别动,要么两端都配。一次只改一端并保留上一个文件,这样回退是两分钟的事,而不是重建。
把每一端的机制、密钥文件和方向记进部署笔记,否则下一个人会读到两个相似的文件,并以为这两个数字应该彼此一致。方向是协调细节,不是安全升级:它只把控制通道的两个方向分开,别的什么都不做。