你用 wg set 添加的对端整个下午都能回 ping,重启之后就消失了。什么都没有损坏:内核从未把这个对端存到别处,只存在于活着的接口里;启动时重建接口的东西,是用你根本没碰过的文件把它重新拼出来的。修复不是再敲一次 wg set。要做的是弄清哪个组件拥有这个接口,修改那个组件的状态,然后证明该对端能扛过当初移除它的那次生命周期事件。

先故意复现一次

在你能亲眼看到它发生之前,不要动手修重启问题。有控制台或带外访问时,记下对端列表,通过拥有该接口的服务重启,然后对比。如果对端还在,说明你的改动已经进了持久状态,你在调试错误的事件。

做这件事时记下三个事实:接口名、启动它的 unit 或配置、以及幸存对端的握手计数是否归零。计数归零说明接口被销毁后重建了;计数不变而对端不见了,说明有东西在你脚下改了配置。

谁拥有这个接口?

WireGuard 本身既没有守护进程,也没有配置文件。是它上面的某个东西在启动时调用 wg,而那个东西才是真相来源。常见候选是 [email protected]、NetworkManager 连接配置、发行版专属的网络 unit,或者自己写数据库的管理面板。

问系统,而不是问发行版文档。systemctl status wg-quick@wg0 和 nmcli connection show 通常各自一条命令就能定案。如果两者都声称拥有该接口,你在动手改之前就已经找到 bug 了:两个所有者每次启动都重写同一个设备,最后执行的赢。

systemctl status wg-quick@wg0 --no-pager
grep -R "Address\|SaveConfig\|PostUp" /etc/wireguard/wg0.conf
nmcli -g NAME,TYPE connection show
wg show wg0 peers

运行状态和启动状态不是同一个文件

wg set 通过 netlink 操作活动设备。它不会写入 /etc/wireguard/wg0.conf、NetworkManager 配置或面板的数据库。之后 wg show 成功,只能证明内核接受了这个对端,不能证明有东西会把它恢复回来。

反方向还有第二个坑。wg-quick 的 SaveConfig 选项会在接口下线时把当前接口状态写回配置文件。开启它之后,接口在线时对文件做的修改可能被随后的关闭覆盖,而你会一口咬定那行原来就在。如果对端反复回来,请在停止之后读文件,而不是之前。

NetworkManager 又是另一套:它拥有该配置并在激活时应用,所以紧邻活动 NetworkManager 连接、手工改过的 .conf 只是装饰。给接口选一个所有者,让另一个管理器别插手。

让改动同时落到两处

先改持久状态,再让所有者应用,最后验证运行状态。这个顺序意味着任何一步失败都只指向一件事,而不是三件。

# 1. persistent state (wg-quick owner)
sudo vi /etc/wireguard/wg0.conf

# 2. apply through the owner, not by hand
sudo systemctl restart wg-quick@wg0

# 3. verify runtime matches the file
sudo wg show wg0
sudo wg showconf wg0

wg showconf 用与文件相同的语法打印活动配置,因此两者可以直接比对。把这份输出当成机密:里面有私钥,不要粘进工单或聊天频道。比对各对端的公钥和允许的 IP,并确认你故意删掉的对端没有回来。

证明它能扛过生命周期事件

再通过所有者重启一次,然后分别确认三件事:对端出现在 wg show 里、有流量后握手计数增加、依赖隧道的应用真的能应答。握手陈旧的对端属于路由或密钥问题,不是持久化问题,这个区分能省掉一次无意义的配置修改。

最后,检查重启恢复了什么。把故意删掉的对端又复活的重启,是同一个 bug 的反向版本,通常意味着某处还在加载旧配置副本。把所有者、文件路径、对端公钥和验证命令记在配置旁边,这样下一个人就不用靠重启生产主机再发现一遍。

相关文章