ios上有很多网络抓包调试工具, 但是都只能抓http/https的包, 理论上来说都是用的NetworkExtension框架的 PacketTunnel应该是可以抓到所有IP包的. 但是由于 PacketTunnel是无法获取到流量包是属于那个app的, 所以就就算显示出来也很难分析和区分.
NetworkExtension框架还提供了另一种 AppProxy的抓包方式, 这种方式需要配置一个描述文件指定要过滤的目标APP. 也可以在代码里获取到流量包对应的APP信息. 并且这种方式是直接过滤tcp/udp包, 不用像PacketTunnel过滤的是ip包还要去自己解析.
文档: Apple Developer Documentation
示例(已测试成功): https://github.com/yarshure/QNEApproxy/
还有一种 ContentFilter( NEFilterProvider)的抓包方式, 也是需要配置特殊描述文件, 也能获取到流量包的app信息, 但是这种方式只能根据事先配置的规匹配后选择允许或中断流量, 不能修改流量.
这个ContentFilter里面的NEFilterDataProvider模块虽然可以获取流量包, 但是由于在严格的沙盒里, 禁止访问网络, 禁止写入文件(可以读文件), 禁止IPC进程间通信, 所以并不能将数据传出来.
但是我们可以让ContentFilter每次都返回needRules, 这样系统就会去请求我们的NEFilterControlProvider模块, 虽然NEFilterControlProvider无法拿到数据包, 但是NEFilterControlProvider可以拿到IP, 端口, BundleID等信息, NEFilterControlProvider不在严格的沙盒里, 可以将(IP, 端口, BundleID) 传给我们的PacketTunnel VPN过滤模块.
这样就可以完整实现, 获取流量包, 获取对应BundleID, 修改流量包了.
https://github.com/networkextension/SimpleTunnel/ 这个里面的ContentFilter模式抓包, 不用配置目标BundleID, 直接抓所有包, 可以获取每个包对应的BundleID. 只要求开发者证书签名get-task-allow权限即可.
实测这两种方式都不会在状态栏显示VPN图标, 可以绕过CFNetworkCopySystemProxySettings的VPN检测.