飞行模式下 VPN 卡在 Connecting:先找上行链路
在飞行模式下停留在 Connecting 的客户端,可能只是没有上行链路。把无线电状态、关联、门户登录和阻断策略分开。
手机显示飞行图标,VPN 客户端已经在 Connecting 上停了两分钟,而配置文件是正确的。一小时前它在同一栋楼里工作正常。没有任何东西损坏:VPN 是由另一张网络承载的连接,飞行模式只是撤掉了承载它的那张网络。客户端不停重试,因为在上行链路缺失时它只会这么做。
让人困惑的是,飞行图标并不告诉你 Wi-Fi 是否可用,Connecting 也不告诉你客户端是在认证还是仅仅在等待。把这两种读数分开,诊断只需要一分钟。
飞行图标不是无线电报告
在受支持的 Android 设备上,Wi-Fi 和蓝牙可以在飞行模式下保持开启,设备会记住你上次的选择。Google 的Pixel 飞行模式指南描述的正是这种行为。所以这个图标只能说明蜂窝网络已关闭,别的什么也说明不了。
要看实际状态,而不是那个字形。adb shell settings get global airplane_mode_on 会返回 0 或 1 表示模式本身,adb shell dumpsys connectivity 会列出设备当前拥有的网络及其校验状态。这两个输出合起来,才能回答图标无法回答的问题。
如果 Wi-Fi 关闭,或者开着却没有关联到任何网络,就没有通往 VPN 端点的路径,重连多少次也不会创建出来。这种情况值得最先排除,因为它是唯一一种正确修复在 VPN 应用之外的情形。
Connecting 实际上意味着什么
客户端可以持有一份已保存的配置、显示它的名字、转着一个转圈图标,而从未接触过任何东西。配置是本地的。建立隧道需要可达的服务器、完成的握手,以及用于路由的接口。只有最后一部分需要能工作的网络,这就是为什么在无线电关闭时前两项仍可能看起来是成功的。
所以这个转圈图标至少与三种情况相符:完全没有上行链路、上行链路无法到达端点,以及到达了但认证失败。它们在屏幕上看起来完全一样,在日志里则完全不同。这就是为什么这些情况下第一个有用的产物是日志,而不是再试一次。
Android 自己的 VPN 文档也在连接建立与单独的始终开启、阻断策略之间划了同一条线。正是这种区分解释了为什么手机可以在离线时看起来受保护,却仍然没有隧道。
值得区分的四种状态
下面四种状态值得命名,因为屏幕把它们渲染得一模一样。
| State | What you will see | What to do |
|---|---|---|
| Airplane mode, Wi-Fi off | No networks in dumpsys, VPN retries forever | Turn Wi-Fi on, or accept that the tunnel cannot exist |
| Wi-Fi on, not associated | Interface exists, no default network | Join the access point |
| Associated, not validated | Network listed, captive-portal flag set | Complete the portal sign-in, then reconnect |
| Validated, tunnel down | Internet works, VPN fails or blocks | Debug the tunnel, not the radio |
第三行在酒店和机场命中了大多数人。关联不等于准入:没有放行手机的门户会欣然接受 Wi-Fi 密码,然后拒绝把流量放行到 VPN 端点。在隧道关闭时先用浏览器登录,通常是唯一的通路。
为什么阻断让它看起来更糟
如果始终开启的 VPN 和无 VPN 时阻断连接同时启用,那么只要隧道没起来,每个被覆盖的应用都会被阻断。这是功能在起作用,不是第二个故障。症状从单个应用失败变成所有东西都失败,读起来就像一个大得多的问题。
这也解释了人们常误读的顺序:飞行模式打开、没有上行链路、应用被阻断、VPN 显示 connecting。阻断是策略在履行职责。为了测试上行链路而关掉策略,会移除你大概想要的保护,并且什么也教不会你。
反过来去检查覆盖范围。哪些应用被覆盖、哪些被排除,配置是按用户还是整个设备。Wi-Fi 一出现就启动 VPN 应用的那种任务只是一个触发器,并不保证在它运行之前没有数据包发出。
一条终结猜测的诊断顺序
从下往上做。确认模式、确认存在网络、确认它已通过校验、确认它能到达本地子网之外的某个东西,然后才去看客户端。adb shell ping -c 3 1.1.1.1 是个粗糙的测试,但它能把缺失的路径与隧道不高兴时仍然存在的路径区分开。
如果网络在列表里而 ping 失败,问题在 VPN 的上游,任何客户端设置都修不好。如果 ping 成功而隧道仍然建立不起来,就在那一刻抓取客户端日志:错误会区分超时与认证被拒,而这两者毫无共同之处。
最后恢复原本应有的状态:如果这是你的常规设置,就允许飞行模式下使用 Wi-Fi,走完门户,再把阻断策略打开。然后重连一次,确认隧道自己就起来了,因为一个只有手动重试之后才工作的配置,下次开机还会失败。