ARTICLE · 1135491
银行App一检测到你开了VPN,就秒变砖头
你肯定遇到过:打开银行 App 转账,结果弹出来一句"检测到您正在使用 VPN/代理,请关闭后重试"。
你把 VPN 关了, App 立刻恢复正常。
问题来了:App 怎么知道你开了 VPN ?它又没偷看你的系统设置——或者说,它偷看了吗?
答案比你想的更技术。银行 App 没有读你的 VPN 配置文件,它只是查了一下系统网络接口列表,发现多了一个"不该出现的网卡"。
VPN 在系统层面到底做了什么
要理解检测原理,先搞清楚 VPN 打开时系统发生了什么。
你的 iPhone 不开 VPN 时,网络路径是这样的:
开了 VPN 之后,变成这样:
关键在那个 utun0。 VPN 在系统里创建了一个虚拟网络接口( tunnel interface ),所有流量先走这个虚拟网卡,再从 VPN 服务器出去。
这就像你寄快递,正常从北京发到上海。但如果你用了 VPN ,相当于快递先绕到新加坡再发到上海。包裹内容没变,但路径变了——多了一个中转站。

银行 App 的检测原理,就是查这个"中转站"是否存在。
第一层检测: CFNetwork 的 __SCOPED__ 字典
这是最核心、最可靠的一层检测,而且不需要任何特殊权限——App Store 审核 100% 通过。
iOS 系统里有一个 C 级别的函数叫 CFNetworkCopySystemProxySettings(),它返回当前系统的代理配置。返回值里有个关键字段叫 __SCOPED__,是一个字典,里面列出了所有当前活跃的网络接口。
不开 VPN 时,__SCOPED__ 长这样:
开了 VPN 后,变成这样:
检测逻辑就是:遍历 __SCOPED__ 的所有 key ,看看有没有这些名字——
就这么几行。核心是 __SCOPED__ 字典里的 key——VPN 创建的虚拟网卡接口名(utun、tun、tap、ppp、ipsec)和普通 Wi-Fi/蜂窝网络接口名(en0、pdp0)完全不同。只要发现了这些前缀的接口,就说明有 VPN 在跑。
这就像你检查一个人身上有没有多带一个钱包——正常出门带一个钱包(en0),突然多了一个暗袋(utun0),那就说明有问题。

第二层检测: NWPathMonitor 实时监控
CFNetworkCopySystemProxySettings 有个弱点:它是一次性调用。调一次返回当前状态,不会在 VPN 状态变化时主动通知你。
银行 App 需要的是实时监控——用户可能先开 App 再开 VPN ,也可能开 VPN 后关了再开 App 。这需要 NWPathMonitor。
NWPathMonitor 是 iOS 12 引入的 Network 框架 API ,它可以监控网络路径的实时变化:
和第一层配合使用:CFNetworkCopySystemProxySettings 负责"首次检查",NWPathMonitor 负责"持续监控"。两层交叉验证,基本上没有 VPN 能逃过去。
第三层检测: SSL 证书指纹校验
前两层检测的是"系统有没有虚拟网卡"。但有些高级 VPN (比如 Quantumult X 的"虚拟网卡模式")不走系统代理,而是直接接管网络层,__SCOPED__ 字典里可能不会出现 utun 接口。
这时候银行 App 会用第三层:SSL 证书指纹校验。
原理是:你用 VPN 连银行服务器时, SSL 握手过程中的证书可能经过中间人代理( MITM )。 VPN 软件为了解密 HTTPS 流量,会用自己的证书替换银行的真实证书。银行 App 在 URLSessionDelegate 里校验证书指纹:
这层的逻辑是:如果 SSL 证书指纹和银行预置的不一致,说明流量被中间人截获了——正常用户不会出现这种情况,只有 VPN 做 MITM 解密时才会。
为什么不用 NEVPNManager ?
iOS 还有一个 NEVPNManager 类,能直接读取系统 VPN 配置信息。但它有两个限制:
所以银行 App 不能用 NEVPNManager。它们用的是不需要任何特殊权限的 CFNetworkCopySystemProxySettings + NWPathMonitor 组合——用公共 API 做到的事情,比用受限 API 还多。
生活化比喻:快递的三个检查站
把你发网络请求比作寄快递,银行 App 就是收件方。
第一层检查( CFNetwork ):收件人查快递面单,看寄件路径有没有经过新加坡中转。正常从北京到上海不经过新加坡,但 VPN 的流量会经过。如果发现路径里有中转站,就是 VPN 。
第二层检查( NWPathMonitor ):收件人装了个实时监控摄像头,不是只在收件时查一次,而是持续盯着——快递在路上突然改道了(用户中途开 VPN ),也能立刻发现。
第三层检查( SSL 指纹):收件人拆开快递,验防伪码。正常银行的防伪码是 A ,如果发现变成了 B ,说明快递在中转站被人拆开过又封上了( MITM 解密)。正常用户不会换防伪码,只有 VPN 做 HTTPS 解密才会。
三层检查,一层比一层深。第一层查路径,第二层持续查,第三层查内容完整性。

为什么银行这么在意 VPN
三个原因:
这也解释了为什么有的银行检测到 VPN 只是弹个提示"建议关闭",有的是直接拒绝服务——风险等级不同,处理策略不同。
不同 VPN 的"对抗"策略
V2EX 上有大量讨论,核心结论是:
__SCOPED__ | ||
utun 接口 | ||
utun 接口 |
V2EX 帖子里的结论是:用 Quantumult X 的"虚拟网卡模式"且不使用系统代理接管,是最可能绕过检测的方式。但这不是一劳永逸——银行可以加 SSL 指纹校验层来覆盖这种情况。
本质上这是一个检测方和规避方的持续对抗——和反爬虫 vs 爬虫的博弈完全同构。
面试速记卡
Q : iOS 上怎么检测用户是否开了 VPN ?
A :三层检测。第一层用 CFNetworkCopySystemProxySettings 读 __SCOPED__ 字典,看有没有 utun/tun/tap/ppp/ipsec 接口。第二层用 NWPathMonitor 持续监控网络路径变化。第三层用 URLSessionDelegate 校验 SSL 证书指纹,检测 MITM 代理。
Q :为什么不用 NEVPNManager ?
A : NEVPNManager 需要 NetworkExtension entitlement ,普通 App 申请不到;而且它只能看到自己创建的 VPN 配置,看不到别的 App 创建的 VPN 。CFNetworkCopySystemProxySettings 不需要任何特殊权限, App Store 审核通过。
Q : VPN 为什么会改变系统网络接口?
A : VPN 在系统里创建虚拟网络接口(如 utun0),所有流量先走这个虚拟网卡,再从 VPN 服务器出去。这个虚拟接口会出现在系统的网络接口列表里, App 可以通过公共 API 查到。
Q : SSL 指纹校验为什么能检测 VPN ?
A :部分 VPN 会做 HTTPS 中间人解密( MITM ),用自己的证书替换服务器的真实证书。银行 App 预置了服务器证书指纹,如果握手时收到的证书指纹不匹配,说明流量被中间人截获了。
Q : VPN 检测和 HTTPS 加密是什么关系?
A : VPN 不破坏 HTTPS 加密——你的流量在 VPN 隧道里是加密的。但 VPN 改变了网络路由路径,系统层面会多出虚拟网卡接口。检测 VPN 不是"破解加密",而是"检测系统网络配置变化"。 HTTPS 保证的是传输内容安全, VPN 检测保证的是传输路径可信。
这篇在知识体系里的位置
属于「 Web 」分类,是「 HTTPS 」和「 CORS 」的延伸。之前讲过 HTTPS (传输加密)和 CORS (跨域限制),这篇讲的是网络层的环境检测——App 怎么感知系统网络配置的变化。
同时关联「安全」分类:之前讲过 SQL 注入和 XSS (输入侧防御), VPN 检测是环境侧防御——不防攻击者输入恶意数据,而是防用户运行环境不可信。
新增知识点:CFNetworkCopySystemProxySettings 的 __SCOPED__ 字典、NWPathMonitor 实时网络路径监控、 SSL 证书指纹校验机制、 VPN 虚拟网卡接口命名规则。