旧应用已经不存在了,但分隧道列表里还留着它的条目。表面上看不出任何问题,所以这一条会在那里待上几个月。然后有人把另一个程序装进同一个文件夹,或者托管配置文件在每次重连时恢复该规则,流量就开始走一条没人规划过的路径。这条排除规则比它存在的原因活得更久。

清理这件事,核心是身份:这条规则现在指向什么,以及这份列表归谁所有。

症状:一条什么都匹配不上的排除

过期条目在日常使用中是看不见的。它会以三种方式暴露出来:你以为会走隧道的应用直接走了本地;新程序继承了旧的例外;或者因为托管配置文件会覆盖修改,客户端拒绝保存编辑。这三种情况看起来像三个不同的 bug,其实是同一个记录管理问题。每一种检查起来都很便宜,误判起来都很贵。

先读规则,而不是先删规则。

弄清规则识别的是什么

分隧道的实现把排除项绑定在不同东西上:可执行文件路径、包名、包标识符或路由。基于路径的规则指向的文件可能已经不存在,也可能已经换成了另一个文件。基于包的规则指向一个身份,新安装可以复用这个身份。要读客户端文档,弄清你正在看的字段,因为同一个文本框在不同产品里含义不同。基于包的情况,可以参考 Android 的VpnService 指南。

显示名称是条目里最不可靠的部分,而人们偏偏只看这一部分。

路径规则和包规则的行为不一样

卸载之后还留下的路径规则,通常会变成无效规则,而无效是好的结果。坏结果是路径被复用,因为新的可执行文件会悄悄继承这条例外。包规则又是另一种情况:产品可能忽略一个不可用的包,可能拒绝它,也可能在新东西占用同名包时继续按名称匹配。

不要把某个客户端的假设搬到另一个客户端上。你要确认自己的客户端在目标缺失时实际会怎么做,最好是在测试机上故意制造这个条件,观察哪个进程继承了这条例外。

通过拥有者移除它

如果列表来自托管配置文件,本地编辑只是临时改动,下次重连时会被恢复。要改配置文件,或者去找它的拥有者,并确认修改在重连后仍然存在。如果列表是本地配置,删除条目后要检查客户端是否重写了配置,而不是把旧配置留在内存里。

空列表不是目标。目标是列表里的条目仍然符合真实需求。

之后测试两个方向

清理之后,既要测试一个仍应被排除的应用,也要测试一个现在应该走隧道的应用。DNS 行为要单独确认,因为解析器策略是另一套控制,与排除列表不同。然后重连一次再测一遍,因为配置文件被恢复,是清理悄悄失效最常见的方式。

在每条保留的例外旁边写一行用途。正是这一行让列表不至于变成博物馆,也让下一次清理变成五分钟的事。

相关文章