握手计数器在更新,接口保留着自己的地址,而发往另一端的 ping 却哪儿也到不了。这个组合让人困惑,因为握手成功看起来像是隧道已经就绪的证明。其实不是:隧道可以已经完全协商好,却没有任何路由把流量送进去,而这是两件彼此独立的工作,由两块彼此独立的状态各自完成。修复完全取决于这两者中缺的是哪一个,所以第一步就是查清这一点。

wg-quick 会在没人要求的情况下把两件事都做掉。NetworkManager 内置的 WireGuard 支持默认也会安装对端路由,这就把可疑范围缩小到了被禁用的选项、另一张路由表,或者通过别的途径导入的配置。

先确认隧道,再追查路由

wg show 会打印接口、对端、端点以及最近一次握手的时长,ip addr show 则确认地址已经存在。握手是近期的,说明密钥、端点和 UDP 通路都在工作。坏掉的东西都在它们的下游:路由、过滤或者名称解析。

接着问内核,它会拿一个真实目的地址而不是假设地址怎么办:ip route get 10.42.7.9。答案会指出出接口和报文将携带的源地址。当它指出的是物理网卡时,无论握手看起来多健康,报文都不会进入隧道。

AllowedIPs 既是过滤器,也是路由清单

AllowedIPs 里的前缀做两件事。它们决定由哪个对端承载某个出站目的地址,并校验入站报文的源地址,这就是加密密钥路由的边界。在 wg-quick 里它们还驱动自动安装路由,而正是这段额外的行为,解释了为什么同一份配置在终端里能用、在桌面客户端里却不行。

本文背后的案例中,配置文件是通过第三方插件导入的,而不是通过内置支持导入的,接口起来时没有前缀路由。把路由表列出来就能立刻看到:ip route show 里只有接口地址的连接路由,远程网段一条也没有。

先问一句:对端路由到底开了没有

动任何东西之前先读设置:nmcli -f wireguard.peer-routes,ipv4.route-table connection show work-wg。当 peer-routes 读出 no 时,受支持的修法是 nmcli connection modify work-wg wireguard.peer-routes yes,然后再重连一次。改用静态路由也能用,但只撑到下次激活,之后会悄悄消失。这个消失就是线索:每天早上像谜一样回来的路由,不是配置文件装的。

如果这个选项已经启用,就用 ip route show table all | grep 10 看看前缀是不是活在另一张表里。非主表里的路由并没有缺失,它只是对只查主表的查找不可见。请把策略路由修对,而不是在上面再叠一条重复记录。

把前缀加在连接上,而不是加在运行中的系统上

在连接编辑器里,WireGuard 页面放着对端及其 AllowedIPs,IPv4 页面放着附加路由。在那里加的路由在重连之后仍然存在,因为它属于这份配置。命令行上的等价做法是用空网关的形式给连接追加一条路由,然后把连接降下去再升起来,让改动生效。

选一个能覆盖所需主机的、最窄的前缀。照抄服务商示例里的 /8 会把恰好落在其中的本地网段一起吞掉,由此产生的故障看起来像隧道坏了,而不是路由太宽。

分流由前缀清单决定

分流没有开关,前缀清单就是决定。一个对端,一个网段给办公室 LAN,一个给实验室网络,它就会把正好那些目的地址送进隧道,其余的一概不管。单台主机需要 /32,两地互相重叠的网段则需要主机前缀,直到有人把某个子网重新编号为止。

选择什么都不走隧道,等于把同一个决定推到极限:最小清单让链路保持在线,普通流量仍走原来的路。把意图写下来,否则下一个读者会把这份短清单当成疏漏,热心地把它加长。

路由表只能有一个主人

wg-quick 和 NetworkManager 都认为接口的路由归自己管。把一份为 wg-quick 写的配置导入,又把 wg-quick 服务也启动起来,就会得到重复或互相冲突的条目,其行为取决于谁最后运行。挑一个主人,把另一个去掉:如果连接由 NetworkManager 管理,就关掉该接口的 wg-quick 单元,并且绝不为同一台设备再添一份配置。

当分流必须跟着物理网卡而不是目的地址走时,你就进入了策略路由,而策略路由同样需要一个唯一的作者。验证的方法是重复 ip route get,然后用一条会把它所选源地址打印出来的命令,去够远程前缀里的主机。如果配置里带了 IPv6 或 DNS,就分开检查。

相关文章