flutter应用网络请求调试一直是业内难题,原因在于dart语言标准库的网络请求不会走wi-fi代理,常规通过配置wi-fi代理来抓包的方式行不通。这给我们日常开发测试造成了很大的阻碍,严重降低工作效率。因此写一篇教程,讲解如何使用reqable对flutter移动应用进行抓包调试。
1. 环境准备
电脑:windows/mac/linux机器,安装reqable客户端(建议2.18.0以上版本)。
手机:android/ios设备,安装reqable移动端app(要求最低2.19.0版本)。
2. 安装证书
首先,启动reqable电脑客户端,完成初始化进入主界面。点击顶部手机图标,打开二维码。
接下来,手机连接到和电脑所在的同一个wi-fi局域网。打开reqable手机app,选择协同模式,扫码上面电脑端二维码进行连接。
连接成功后,开始下一步,安装证书。由于是对手机抓包,需要在手机安装证书,而不是在电脑安装证书,所以电脑上的证书可以选择不安装。
reqable在上面选择协同模式初始化的时候,已经自动将电脑的根证书同步到了手机,安装证书只需要在手机上操作即可,无需将证书手动从电脑拷贝传输到手机。注意:手机抓包,必须安装电脑证书到手机。如果app是以独立模式初始化,app会生成和电脑不同的根证书,扫码连接电脑后需要手动同步根证书到手机再安装。
android设备
注意,flutter应用程序只信任android系统目录的证书,不会信任用户证书。native应用我们可以通过配置 network_security_config.xml 文件或者降低targetsdkversion到33来让应用信任用户证书,但是这个对于flutter应用是不行的。
因为dart sdk中已经强行写死了只信任系统目录下的证书。这个逻辑定义在 runtime/bin/security_context_linux.cc 中,有兴趣可以去翻看源码。
// on android, we don't compile in the trusted root certiicates. instead,
// we use the directory of trusted certificates already present on the
// device. this saves ~240kb from the size of the binary. this has the
// drawback that ssl_do_handshake will synchronously hit the filesystem
// looking for root certs during its trust evaluation. we call
// ssl_do_handshake directly from the dart thread so that dart code can be
// invoked from the "bad certificate" callback called by ssl_do_handshake.
const char* android_cacerts = "/system/etc/security/cacerts";
loadrootcertcache(android_cacerts);
android设备上要安装证书到系统目录,目前只有两种方式:
方式一:root设备,解锁system分区,将证书复制到 /system/etc/security/cacerts 目录。可以按照reqable中的提示进行操作。
adb root
adb shell avbctl disable-verification
adb remount
adb push reqable-ca.crt /system/etc/security/cacerts/证书hash.0
方式二:设备刷magisk环境,从reqable手机app中下载证书模块,安装即可。
根证书安装成功后,reqable手机app会有证书已安装的提示。如果已经安装,但仍然提示证书未安装,可能是操作出错,请复查安装步骤。不要怀疑检测有问题!
ios设备
ios安装证书要简单很多,标准三个步骤。
a. 下载描述文件。可以从reqable手机app直接保存,也可以启动浏览器下载描述文件。
b. 设置 -> 下载的描述文件 -> 选择文件 -> 安装。
c. 设置 -> 通用 -> 关于 -> 证书信任设置 -> 打开开关。
可以看到ios设备安装证书要简单很多,所以我们一般推荐使用ios设备调试。
更多有关证书安装的说明,可以查阅reqable官网文档。
3. 增强模式
在手机app上,reqable提供了两种网络流量捕获模式,一种是常规模式,一种是增强模式。这里先简单介绍下两种模式的区别。
常规模式,和配置wi-fi代理效果一样,但是不需要用户去手动配置wi-fi代理。可以对绝大多数应用的流量分析,包括浏览器等。
增强模式,强制捕获所有的流量,包括不走wi-fi代理的网络请求流量,例如我们需要解决的flutter应用。在android设备上,增强模式还可以获取到流量来源的应用信息。
默认情况下,android是自动开启增强模式的,用户无需手动开启。ios设备有些特殊,手机在飞协同模式下无法开启增强模式,必须连接协同设备(电脑),并在标题菜单中手动开启。
对于flutter应用,请一定要开启增强模式。增强模式开启后,标题后面会出现一个钥匙🔑标记。
4. 实战演示
首先,创建一个flutter空项目,这个项目我们简单改改代码作为测试应用。
flutter create capture_test
加点代码,比如点击 + 按钮,发送一次http请求。
void _incrementcounter() async {
final httpclient httpclient = httpclient();
final httpclientrequest request = await httpclient.geturl(uri.parse('https://httpbin.org/get'));
request.close();
}
通过下面的命令,启动flutter应用。
flutter run -d 设备id
接下来,我们开始测试。reqable手机app中开启调试,电脑端同时会进入调试状态,如果电脑没有自动开启调试,那么手动启动一下。
正常情况下,应该能成功抓到http请求了,如下图。
如果出现下图这种客户端ssl握手失败的提示,说明是手机上证书没有安装成功。
这种情况,在命令行控制台中也能看到flutter的报错。
e/flutter (24436): [error:flutter/runtime/dart_vm_initializer.cc(41)] unhandled exception: handshakeexception: handshake error in client (os error:
e/flutter (24436): certificate_verify_failed: unable to get local issuer certificate(handshake.cc:393))
e/flutter (24436): #0 _securefilterimpl._handshake (dart:io-patch/secure_socket_patch.dart:99:46)
e/flutter (24436): #1 _securefilterimpl.handshake (dart:io-patch/secure_socket_patch.dart:143:25)
e/flutter (24436): #2 _rawsecuresocket._securehandshake (dart:io/secure_socket.dart:920:54)
e/flutter (24436): #3 _rawsecuresocket._tryfilter (dart:io/secure_socket.dart:1049:19)
e/flutter (24436): <asynchronous suspension>
q:只有android设备,且无法将证书安装到系统证书目录,那么该怎么办?
修改代码强行信任任意证书,通过这个还可以跳过前面证书安装那一步,真正的无门槛,但就是不安全。所以请注意:应用正式发行版本务必删除或者绕过此项设置。
httpclient.badcertificatecallback = (x509certificate cert, string host, int port) => true;
q:只想用电脑,不想用reqable手机app协同,怎么办?
同样要修改代码,配置网络请求必须走代理:
httpclient.findproxy = (url) {
return 'proxy 电脑ip:电脑抓包端口';
};
好了,本篇教程到这里基本就结束了。
本文作者:megatronking
发表评论