如何阅读受管工作应用的 VPN 与代理状态
受管手机上的 VPN 图标能证明的东西很少。读活跃网络、它的能力与有效代理,然后按每个值本来的样子去读。
受管手机上工作应用失败,有人检查 VPN 开关,看到它已打开,就宣布路径健康。大多数这类诊断到此为止,而这太早了:一个活跃的 VPN 传输并不能说明这个应用的请求用过它,而真正生效的代理可能是按应用区分的,也可能是由 PAC 文件选择的,并不会显示在设置里。从你正在排查的具体应用和配置文件入手,然后去读平台自己对这条路径的看法。
从应用和它的配置文件入手
带工作标记的应用通常运行在拥有独立网络策略的单独配置文件里。同一部手机上的个人浏览器不能作为它的证据,同事那台管理方式不同的设备上的结果也不能。读取任何信息之前,先记下这个应用属于哪个配置文件。
在设置里列出已配置的 VPN 条目,并记下每一条归谁所有。三星版本之间的菜单标签会变动,所以要描述条目本身,而不是找到它的路径。灰色或受管的条目属于管理该设备的人;把它当作实验关掉,会改变你要测量的东西,还可能违反策略。
读取平台报告的状态
在你支持工具的现有 activity 内,在 API 23 或更高版本上,可以读取网络状态而不发送任何字节。这次调用需要常规的 ACCESS_NETWORK_STATE 清单权限来完成能力读取。
val cm = getSystemService(android.net.ConnectivityManager::class.java) ?: return
val network = cm.activeNetwork
val caps = network?.let { cm.getNetworkCapabilities(it) }
val hasVpn = caps?.hasTransport(android.net.NetworkCapabilities.TRANSPORT_VPN)
val proxy = cm.defaultProxy每个值回答一个范围很窄的问题。活跃网络是调用进程在那一刻的默认网络。能力检查告诉你这个默认网络是否由 VPN 支撑。代理调用报告有效的默认 HTTP 代理,返回的对象可能描述静态代理,也可能描述 PAC 脚本。
如果你需要按网络查看而不是默认网络,请读取同一网络的链路属性,并与 cm.getLinkProperties(network)?.httpProxy 比较。由设备管理安装的代理会出现在默认代理调用里,而不会出现在链路属性里,这是快速区分策略所给代理与网络所给代理的方法。
把输出留在你的支持渠道里,而不是公开报告。代理主机名、PAC 地址和内部后缀会暴露贵组织如何路由流量,而描述故障并不需要其中任何一项。
狭窄地解读每一个字段
网络为 null 或能力对象为 null,意味着调用方的网络状态不可用,或者在读取过程中发生了变化。这并不意味着没有 VPN。把它当作未知,等应用回到前台后再读一次,而不是当作否定结果。
VPN 传输是这些肯定信号中最弱的一个。任何持有 VpnService 的应用都会产生一个,包括一个从不把你的流量发往任何地方的本地过滤应用。所以 true 只说明存在一个由 VPN 支撑的默认网络,并不说明用了贵组织的出口,更不说明发生了检查。
默认代理为 null,意味着这个 API 对当前有效配置没有报告任何默认 HTTP 代理。它排除的东西很少:应用可以自带 SOCKS 设置,实现自己的 HTTP 客户端,或者被设备根本不知道的网关代理所引导。
PAC 就是那种让单值答案失效的情况。脚本可以把一个目的地走代理,把另一个直连,所以同一个应用在一秒内的两个请求可能走不同的路径。而把套接字绑定到选定网络、或调用 bindProcessToNetwork 的应用,根本没有义务遵循默认值。
这份快照不能告诉你什么
这不是历史。这里没有任何东西记录失败请求走了哪条路径,而失败之后的一次成功读取,也不能作为关于那次失败的证据。它也不是清单:你拿到的是调用进程的默认网络,而不是每个应用私有连接的列表。
它也没有说明套接字之上发生了什么。在受管设备上失败的 TLS 握手,可能是信任库问题、固定校验不匹配,或者代理拒绝的某个名称,而这些都不会出现在连接性读取里。
这就是为什么两半要合起来看:快照缩小了该往哪里查,而应用自己的诊断说明实际失败的是什么。
以管理员用得上的形式报告
给出受影响的应用、配置文件、时间戳,以及失败的确切阶段:名称解析、TCP 连接、TLS 握手或某个 HTTP 状态。按读取到的原样补上快照值,null 就写成 null,而不是写成「无」。记下同一配置文件里的其他应用是否也以同样方式失败,这能把应用问题与整个配置文件的路径问题分开。
然后停下来,让这条路径的负责人回应。不要把企业证书、代理地址或 VPN 条目当作可以移除管理或绕过获批路线的许可;那会把一个支持案例变成策略事件。
默认代理契约很短,值得读一遍,因为它精确定义了这次调用报告的是哪个代理,而对这份快照的每一种过度解读,都始于假定它报告得更多。