VPN 图标显示已连接:它到底告诉了你什么
已连接的图标可能只意味着一个应用的隧道或一次探测成功。先确定范围,把过期的读数当作未知,并把拦截与提示分开。
绿色的 VPN 图标是对某件事的断言,而有用的问题是:它断言的是什么。在手机上,它可能反映某个客户端的隧道、当前网络的传输方式,或一次成功访问内部页面的请求。这些观测来自不同的来源,以不同的频率刷新,并且可能在同一块屏幕上互相矛盾。正因为如此,图标看起来一切正常时,你面前的浏览器却可能打不开网页。
先划定范围,再去看颜色;否则颜色回答的将是一个没人提出的问题。
图标回答的问题,比你以为的要窄
从一个明确的范围开始,例如使用已批准个人隧道的个人浏览器。工作配置文件的隧道并不能回答个人应用的问题,而按应用配置的 VPN 可能恰好排除了你正在测试的那个浏览器。本地过滤客户端可能显示已连接,却什么也没有发给远程网关,因为它的隧道在设备上就终止了。
在 Android 上,指示图标背后的网络回调报告的是某个网络的传输方式与能力。VPN 传输说明的是哪张网络承载流量,而不是哪些应用或地址族在使用它。
用证据建立状态表
三种或四种状态就够了,前提是每种状态都点明它背后的证据。下表的列从可观测的事实出发,而不是从你想显示的颜色出发,这样才能避免把过期读数当成成功。
| Signal actually observed | What it establishes | What remains open |
|---|---|---|
| Target client reports an established tunnel | That client believes its tunnel is up, within its own scope | Other apps, other profiles, other address families |
| Active network exposes a VPN transport | Some tunnel carries the current network | Which app it belongs to and where it exits |
| Probe to a private host returned fresh data | One request reached one destination at one time | Everything the probe does not touch |
| Callbacks stopped or data is older than the refresh window | Nothing current is known | Any statement about the tunnel state |
实际中最常被丢掉的正是最后一行。当数据源死掉时仍保留最后一个值的指示灯,等于把历史当成现在报告,而用户会把它读成实时状态。把这种情况标为过期或未知,并选择不含隧道意味的措辞。然后让标签在数据源停止的那一刻就改变。
查清设备实际报告了什么
实体指示灯或小组件应当由受支持的观测驱动,而不是由对最后一次已知正常状态的猜测驱动。下面这些 Android 命令无需安装任何东西,就能显示传输方式与平台的常连配置。
adb shell dumpsys connectivity | grep -i -A4 vpn adb shell settings get secure always_on_vpn_app adb shell settings get secure always_on_vpn_lockdown adb shell dumpsys netstats | head -40
常连相关的键值说明平台是否被配置为保持隧道、并在没有隧道时拦截流量;它们并不说明隧道此刻是否健康。在把任何东西显示为已连接之前,先用一次新的探测去对照那份配置读数。
如果观测无法继续,显示界面必须能够说出这一点。一盏接在已经不再运行的自动化上的灯,比没有灯更糟,因为它在断言一个没人测量的状态。
把警告与强制执行分开
能察觉断线的自动化是在事件之后才触发的,所以它不能充当那道阻止数据包在空档期泄漏的边界。如果必须禁止直接回退,就配置平台的拦截策略,并故意关掉隧道来验证它。指示灯负责报告,策略负责执行。
为强制合规而关闭网络接口的警告任务,也可能把设备锁在它所需要的重连之外,形成一个隧道再也回不来、警告再也清不掉的循环。
先决定观测者不确定时界面应当显示什么,然后停掉观测者来测试这种情况。如果答案仍然是已连接,那说明指示灯在测量过去。