单应用的终止开关听起来是谨慎之选:隧道断开时只有工作客户端失去网络,其他一切照常运行。随后有人发现,个人浏览器照样加载了页面,随同一套件安装的同步助手仍在反复重试,缓存中的域名仍解析到一条从未经过隧道的地址。功能上的标签和它真正保护的连接集合是两回事。先确定受保护的集合,因为正是这个集合决定了:逐应用执行还是整机锁定,才是诚实的描述。

从集合出发,而不是从标签出发

逐应用策略保护被选中的应用。整机锁定针对更宽的网络边界,通常为本地打印、管理流量或强制门户保留有据可查的例外。除非能回答三个问题,否则两种标签都不完整: 被排除的应用会怎样,这些应用启动的辅助进程会怎样,保护不可用时新开的连接会怎样。

在改动任何客户端设置之前,先把答案写下来。如果要求是“这个工资客户端绝不能经隧道之外访问互联网,而我的浏览器可以”,集合很小,逐应用执行正合适。如果要求是“本机上除更新服务外,任何东西都不能在无保护状态下访问互联网”,那么任何逐应用策略都做不到,因为问题恰恰出在那些你未点名的应用上。

逐应用执行匹配的是标识符,而不是程序名

Android 通过包提供逐应用 VPN,其 VpnService 文档说明了它与常开模式和阻断如何配合。iOS 通过管理描述文件配置逐应用 VPN,按应用或按域匹配。Windows 与 Linux 根本没有按进程的路由,因此同一思路改用限定到某个程序的防火墙规则,或改用匹配属主用户的规则来近似。

边界就是标识符,而标识符很容易被绕过。把 URL 交给系统浏览器的应用,或在查看器中打开文档的应用,会转入你的策略从未点名的进程。 断开即终止选项同样不是包过滤器:它只会杀死你配置的那个应用,而子进程、队列工作线程或浏览器标签页仍能让既有套接字保持存活。

锁定覆盖逐应用策略看不见的部分

整机锁定取消了选择。凡不属于隧道的出站数据包一律丢弃,包括应用策略从未知道的进程流量。在 Android 上,这就是常开 VPN 加上阻止连接设置,执行发生在系统层,而不是客户端窗口。在桌面上,则是一条持续生效的防火墙规则,或指向不可达网关的默认路由。

代价是其他一切都会停止,因此例外必须成为设计的一部分,而不是事后补丁。本地打印机、服务发现、强制门户登录、管理代理和系统更新各需一个有据可查的开口,因为每一项都是在隧道断开时仍然敞开的路径。锁定的强度只取决于那份清单里最短的一条。

DNS、IPv6 与后台辅助进程掩盖了泄漏

受保护应用无法解析域名,并不能证明缓存答案或直连 IP 流量已被阻断。如果解析器在隧道之外仍可达,域名会解析成功而连接失败,看起来像在工作的终止开关,其实不是。更糟的是,缓存记录可能指向隧道并不承载的地址,于是连接直接外发,而应用却报告 VPN 错误。

IPv6 在每个运行它的平台上都需要自己的规则,因为 v4 的丢弃规则并不覆盖 v6 路由。在移动端,私有 DNS 设置可能把解析移入设备策略并不检查的加密通道。后台辅助进程则是桌面上的常见元凶:托盘里的更新器或同步进程先于 VPN 客户端启动,并保有自己的连接,因此永远看不到已经改变的路由。

测试三个应用与两种切换

TestWhat it proves
Included app, by name and by direct IPthe policy is applied, not just the resolver
Excluded app, same checksthe exclusion is intentional and documented
Helper or updater processnothing inherited an older route
Tunnel drop, then Wi-Fi to cellularthe block survives the transition

每行跑两遍,一遍用主机名,一遍用字面地址;若网络支持,再跑一遍 IPv6。通过意味着:被包含的应用停止了,被排除的应用按你写下的方式运行,辅助进程没有溜出去。把你认为可接受的直连行为记录下来,下一位管理员才能区分有意的例外和故障。

然后用一句话描述结果,点名应用与条件,例如:工资客户端在隧道外没有路由,浏览器按设计直连,隧道断开时其他一切停止。如果这句话很难写,说明策略仍是两套互相打架的策略。

相关文章