Android VPN 与应用权限:那条警告到底意味着什么
Android 的 VPN 授权对话框给出的只是报文层面的一个位置,而不是访问你的邮件、照片或联系人。本文说明这条边界实际划在哪里。
Android 上有两个对话框总被混为一谈:VPN 授权提示,以及应用为获取你的数据而提出的权限请求。前者交出的是网络中的一个位置,也就是报文可以被读取和改写的那一点。后者交出的是被 Android 逐个应用守护的已存内容。把它们当成同一件事,要么夸大了隧道能看见什么,要么严重低估了一个执意为之的应用接下来会索要什么。
授权对话框实际交出的东西
一个实现 VpnService 并声明 BIND_VPN_SERVICE 的应用,会请求系统让它成为设备的 VPN。授权通过后,框架会创建一个 tun 接口,并把该接口的文件描述符交给应用。此后应用所做的一切都经由这个描述符:它从中读出 IP 报文,决定如何处理,再把报文写回去。
该接口的范围是明确的。路由决定哪些目的地会被捕获,addAllowedApplication 或 addDisallowedApplication 决定哪些应用向它供流。一个只列出两个应用的按应用 VPN看不到设备的其余部分。
这是报文层面的授权,不是数据层面的授权。服务看到的是应用交给网络栈、发往某个目的地的字节。它拿不到发送方应用的私有存储、数据库文件,也拿不到其已解密的内存。应用保存在自身沙箱里的文件,其读取难度与从前完全相同。
报文视野止步之处
TLS 在隧道内仍然发挥作用,因为握手的双方是应用与服务器,而不是应用与 VPN。VPN 转发的是它没有会话密钥就无法解密的密文。正因如此,单靠一条隧道并不会暴露 HTTPS 页面或受保护邮件会话的内容。
密文周边的元数据则是另一回事,多数自信的断言正是在这里崩塌。目的 IP、端口、报文大小与时间全都可见,再加上 TLS ClientHello 里的服务器名——即便在 TLS 1.3 之下,它也通常是明文发送的。Encrypted Client Hello 改变了这一点,但并未普及。查询以明文发出时,普通 DNS 同样轻易泄露域名。
更旧或配置有误的协议交出的更多。明文 HTTP、不带 TLS 的 IMAP,以及若干游戏与 IoT 协议,会把自身载荷暴露给任何持有 tun 描述符的一方。
从不随之而来的那些权限
批准 VPN 并不等于批准联系人、短信、照片或媒体库。那些是各自独立的运行时授权,每一项都有自己的对话框,也都能在应用设置页里走各自的撤销路径。想要通话记录的应用必须像其他应用一样提出请求,而你完全可以拒绝,同时保留隧道。
真正需要留意的是证书安装,因为它看起来像 VPN 配置的一部分,其实不是。把用户 CA 装进凭据存储,会改变 Android 接受哪些证书;而自 Android 7.0 起,目标为 API 24 或更新版本的应用会忽略用户自行添加的 CA,除非其网络安全配置通过用户信任锚点主动选择接受。坚持要求安装 CA 的客户端,可能在做合法的企业拦截,也可能在索取 VPN 对话框从未提到的权限。
无障碍访问的服务则更远。开启无障碍的服务可以读取其他应用的屏幕内容,而这是任何报文层面的位置都给不了的。
本地过滤器还是远程网关
同一套 API 覆盖了两类值得不同程度信任的产品。设备上的防火墙或广告拦截器拿到 tun 描述符后就在本地应答流量,从不把它发往自己运营的服务器。真正的隧道会把这些报文转发到别处的网关,那边的运营者从另一端看到同样的元数据,同时决定什么可以返回。
区分它们的实用办法是:分别在开启和关闭 VPN 时查看自己的公网地址,并看看通知里是否点明了远程终点。如果地址从不变化,流量很可能只是在设备内部兜圈子。
两种情况都仍然是报文层面的位置。区别在于出口处还站着谁。
审计你批准了什么
打开“设置”,再进“网络和互联网”,然后进“VPN”,读那条记录本身,而不是状态栏里的图标。“始终开启的 VPN”和“在没有 VPN 时阻止连接”是让接口保持存活、切断泄漏的设备设置,它们并不扩大任何权限。在同一个界面里,你可以忘记该配置并撤销授权。
接下来逐项核对其他权限。“应用信息”显示客户端持有哪些运行时授权,“安全”设置则显示当时是否安装了用户证书。两者都可以单独移除。
真正值得回答的问题很窄:哪些报文进入了这个服务,它们去了哪里,实现又保留了什么。对话框里的其余内容都是噪声。VpnService 参考文档才是该接口究竟暴露了什么的权威清单。