分流隧道:为什么链接在设定的 VPN 之外打开
路由跟着打开套接字的进程走,而不是跟着向你展示链接的 App 走。在扩大排除名单之前,先证明到底是哪个程序在连接。
把 App 放进隧道,并不会把它的路由一并带到这个 App 启动的任何东西上,尽管界面看起来像那么回事。链接把请求交给另一个程序,那个程序打开自己的套接字,平台把规则套用到新进程上,而不是套用到显示文本的那个进程上。隧道策略真正看到的是第二个进程,而它并不是你配置的那个。
因此,被纳入的 App 可以打开一个位于隧道之外的浏览器。被排除的浏览器也可以把工作交回给位于隧道之内的 App。这种反差的两种方向都是正常行为。
工作流里没人配置的那一段
按 App 的策略是针对某个可执行文件或包的身份写的,每条连接都在创建的那一刻被评估。浏览器、文档查看器、媒体播放器以及系统的分享面板各自带着自己的身份,也各自拿到自己的判定。深链接传递的是数据,不是策略。
这就是为什么观察结果显得随意:同一次点击会有两种走法,取决于由哪个处理程序来响应。隧道内的邮件客户端在隧道外的浏览器里打开链接,页面于是从你家的地址加载。隧道外的浏览器在它内部的查看器里打开文档,文件便经由出口抵达。两种结果都不是客户端的故障。
已经在运行的处理程序会让情况更糟。如果浏览器本来就开着,链接就变成发给现有进程的一条消息,那个进程保持着启动时的路由。关掉再重开处理程序会改变结果,这正是问题从不按需复现的原因。
| Platform | Policy object | What it is evaluated against |
|---|---|---|
| Android | Per-app VPN allowlist | Package name of the process opening the socket |
| Windows | Application traffic filters | Application path in the filter rule |
| Linux | UID or cgroup routing rules | Owner of the socket, which can be a different program |
究竟是哪个进程建立了连接
与其推理,不如测量接收端。保持隧道开启,点一个无害的链接,然后看看新程序持有的套接字。
ss -tnp state established '( dport = :443 )' Get-NetTCPConnection -State Established | Select-Object RemoteAddress,OwningProcess
第一条命令列出 Linux 上每个已建立套接字背后的进程,第二条在 Windows 上做同样的事,靠解析所属进程的标识符。把这个进程名与你策略里的名字对比。如果名字是浏览器,而浏览器被排除在外,那么这次点击是按设计离开隧道的,不是故障。把策略规则和活着的套接字对上,就是全部方法。
在处理程序已经运行时重复检查一次,再在它关闭时检查一次。两个结果可能不同,而这个差别解释了大多数关于链接溜出隧道的间歇性报告。
覆盖范围是工作流的属性
如果一项任务必须从头到尾待在隧道里,那么它能触达的每个组件都得在策略之内:启动器、处理程序、查看器,以及平台插在它们之间的任何代理。更宽的覆盖往往才是诚实的答案,也比逐个审计分享目标更便宜。
为了修一个应用就去排除系统代理,是常见的错误。代理是共享的,所以这项排除会跟着所有使用同一条路径的其他应用走,通常没人察觉,直到几周后有人报上来。排除某个组件之前,先读一读还有谁依赖它。
身份和路由也要分开看。链接可能携带会话令牌或账户标识,无论请求由哪个出口接收。路由正确的点击,仍然能准确告诉目的地是谁跟了过来。
要记录的是工作流,而不是第一个勾选框。当一项任务横跨四个程序时,那张画着四个程序的图才能预测流量往哪走,而单应用的设置只是它的一行。