1. 为什么要在Windows上用USB过Charles抓包
做移动端开发或者接口联调的朋友,大概率都用过Charles抓包工具。它在Windows上配合手机抓HTTPS请求,常规思路是让手机和电脑连同一个WiFi,然后把手机WiFi代理指到电脑IP和8888端口。这个方案本身没毛病,也挺稳,但真正落地的时候你会发现一堆烦心事:公司办公网络开了AP隔离,手机和电脑虽然在同一个WiFi下但根本不通;会议室、工厂车间这些地方网络信号差,WiFi代理经常断;测试手机是那种只能插SIM卡上网的机型,压根连不上公司WiFi;还有一部分Android设备在部分系统版本下对WiFi代理支持不友好,配置完代理后发现应用不走代理通道。
这个场景我碰到的次数多到数不清。每次临时在客户现场要抓个包核对问题,第一反应就是找WiFi,找不到就特别被动。后来才把思路转过来:USB数据线就插在电脑上,既然adb能把数据从手机通过USB通道转发到电脑,那Charles的代理服务能不能也走这条USB物理通道?答案是可以的,而且这种方式比WiFi稳定得多。
简单说,这个方案的核心思路是:电脑上Charles照常监听8888端口,但手机不走WiFi代理,而是通过adb反向代理机制,把手机上发往127.0.0.1:8888的流量,沿着USB数据线直接转发到电脑的8888端口。应用侧只需要把所有请求指向127.0.0.1:8888,Charles就能完整看到从应用发出的每一个HTTPS请求。整个过程不依赖局域网,不依赖网段,也不依赖WiFi信号强弱,物理链路就是那根USB线,想断都难。
这篇文章写给谁?写给在Windows电脑上开发调试Android应用的工程师、做小程序前端联调的同学、需要排查第三方SDK网络请求的测试人员,还有那些跟我一样被WiFi代理折腾到没脾气的人。下面我按完整流程把原理、配置、实操、常见坑都走一遍,照做基本几分钟就能把环境搭起来。
2. 先搞清楚USB通道抓包到底是怎么工作的
2.1 Charles替你做的那点事
Charles本质上就是一个HTTP中间人代理。手机上的应用发HTTPS请求时,Charles会把自己伪装成目标服务器,用自己生成的证书跟应用完成TLS握手,然后应用实际上是跟Charles建立的安全连接。与此同时,Charles再作为客户端去跟真正的服务器建立另一条TLS连接。这样两条连接都由Charles中转,它自然能看到明文内容。这也就是为什么你必须把Charles的CA根证书安装到手机的“系统受信任凭据”里——因为应用的TLS握手验证的是证书链,如果根证书不被信任,应用会直接拒绝连接。
在这个机制里面,代理地址指到哪儿是核心问题。WiFi方式下代理地址填的是电脑在局域网里的IP,比如192.168.1.100。USB方式下没有局域网IP的概念,手机和电脑之间只有一条USB虚拟网卡链路,普通情况下应用没法直连电脑的8888端口。adb reverse正好补上这个空白。
2.2 adb reverse到底做了什么
Android调试桥(adb)自带一个反向转发功能,命令格式很直白:
adb reverse tcp:8888 tcp:8888这条命令的意思是:把手机上所有访问127.0.0.1:8888的TCP连接,通过USB线转发到电脑本机的8888端口。注意这个转发是在adb服务层面完成的,adb服务跑在电脑上,数据经过USB物理通道,完全不经过手机WiFi网卡,也不经过局域网。
所以整个链路就是:
App -> 127.0.0.1:8888(手机侧) -> adb reverse转发 -> USB线缆 -> adbd进程 -> Charles监听端口8888(电脑侧)这个机制在Android 5.0以上的所有版本都支持,也不需要root权限,唯一的前提是手机开USB调试并且授权了这台电脑的调试指纹。所以从技术门槛来说,比WiFi代理更容易搞定,因为不用在手机上敲IP、不用反复确认是否连上同一个WiFi。
2.3 为什么USB方式比WiFi稳定
WiFi代理不稳定,大多数情况下不是Charles的问题,而是数据链路的问题。手机走WiFi发出的每个请求都经过无线AP,再由AP转发到电脑网卡。这中间只要AP有信号波动、信道干扰、漫游切换,TCP连接就会中断或者超时。而USB线是点对点的物理链路,不存在无线干扰问题,单位时间内的吞吐量稳定得多。
另外一个痛点Windows用户应该深有体会:电脑开热点给手机用的时候,Windows自带的移动热点功能偶尔会抽风,连上之后手机上不了网,或者DNS解析卡死。USB方式完全绕开这个环节,手机自身的移动网络或者WiFi该上网还正常上网,只是代理流量走了USB线,两件事互不干扰。这在排查SDK问题时是巨大的效率提升,因为你可以一边开着手机流量跑业务,一边在电脑上看每个请求的具体内容和时序,不会因为代理导致整个网络环境变动。
3. Windows环境准备与Charles基础设置
3.1 按部就班装好Charles并注册
Charles官方下载地址是charlesproxy.com,当前主版本是4.x,支持Windows 10和Windows 11。安装包很小,按默认路径安装就行,装完桌面上出现Charles图标,第一次启动会让你填注册码。网上流传的注册码很多都失效了,与其去找注册机,不如用最朴素的思路:官方给试用期,每次启动会有30秒的等待窗口——但只需要在弹窗出现后手动关掉,功能上只是限制会话保存时长,调试抓包完全不影响。
如果你需要长期使用,请支持正版,个人许可大概几百块人民币,对日常开发来说不算贵。这里多说一句:不要用什么"Charles注册码生成器"之类的东西,来路不明的工具往往掺杂了不干净的东西,装进电脑得不偿失。
3.2 打开SSL Proxying并配置端口
Charles安装之后默认就开了HTTP代理,监听端口是8888,在菜单栏Proxy -> Proxy Settings里能看到。SSL Proxying默认是关闭的,必须手动打开才能解密HTTPS流量。这一步经常有人忘记,结果抓到的全是加密的乱码或者直接看不到App发出的HTTPS请求。
配置方法如下:
Proxy -> SSL Proxying Settings 勾选 Enable SSL Proxying 点击 Add,Host填 *,Port填 *Host和Port填通配符的意思是:无论请求目标是哪个域名、哪个端口,都尝试解密。这种配置在开发调试阶段最省事。要是只关心特定接口,也可以只填域名,比如api.example.com端口443,但建议一开始全放开,避免漏看。
3.3 在Windows上安装Charles根证书
Charles的解密能力依赖它自己的根证书。Charles首次启动时会自动生成一个CA证书,你需要把它安装到Windows的“受信任的根证书颁发机构”,否则你的Windows本地程序(比如某些桌面应用走的代理)会报证书错误,浏览器也可能拦截。
操作路径是:
Help -> SSL Proxying -> Install Charles Root Certificate点击之后会弹出证书安装向导,注意安装位置必须选“本地计算机”,存储位置选“受信任的根证书颁发机构”。装完之后在浏览器里访问一下任意HTTPS网站,地址栏没有飘红就说明Windows侧信任没问题。
Windows上还有个容易忽略的细节:Charles根证书是有有效期的,默认大概十年。过期之后需要重新安装,否则部分应用会突然开始拒绝连接,排查半天最后发现是证书过期,很气但也没办法,先把时间维度查一遍。
4. USB抓包实操全流程:从手机设置到看包
4.1 手机端开启USB调试
不同品牌的手机开启USB调试的入口不太一样,但大逻辑一致:
设置 -> 关于手机 -> 连点7次“版本号” -> 进入开发者模式 设置 -> 开发者选项 -> 打开USB调试华为、小米、OPPO、vivo这些主流机型,有的还需要在开发者选项里额外打开“USB安装”和“USB调试(安全设置)”。第一次插USB线时手机会弹窗询问“是否允许USB调试”,勾选“始终允许”,然后点确定。
注意有一个坑:部分手机在插上USB线后会默认进入“仅充电”模式,这样adb设备列表里看不到设备。解决办法是下拉通知栏,把USB连接模式改成“传输文件(MTP)”或者“传输照片(PTP)”,只要不是纯充电就行。这个我踩过不止一次,每次换一台新手机插上去,adb devices半天没反应,结果就是USB模式没切对。
4.2 让电脑识别到手机
Windows上安装adb工具,最简单的方式是下载Android SDK Platform-Tools,解压之后把platform-tools目录加入PATH,或者直接在命令行里切到该目录操作。验证手机连接状态的命令是:
adb devices正常情况下输出:
List of devices attached 1234567890abcdef device如果显示的是unauthorized,说明手机端的授权弹窗没有点允许;如果显示offline,大概率是USB线质量差或者端口供电不足,换一根原装线或者换一个USB口试一下。这里强烈建议优先用电脑主机后面板的USB口,前置面板或者扩展坞的USB口在传输稳定性上确实要差一些。
4.3 执行adb reverse并验证链路
确认设备在线之后,执行:
adb reverse tcp:8888 tcp:8888没有任何输出就代表成功。想确认转发是否生效,可以在手机上看一看。但更直观的验证方式是:电脑上先开一个本地HTTP服务,比如Python临时服务:
python -m http.server 8888然后在手机浏览器里访问http://127.0.0.1:8888,如果能看到Python服务返回的目录列表,就说明整条USB转发链路是通的。这个验证法我每次都做,可以彻底排除“以为是Charles的问题,其实是转发没生效”的迷惑。
验证完,把Python临时服务停掉,接着在Charles的Proxy Settings里确认勾选了HTTP代理的Enable Transparent HTTP Proxying,因为Charles默认开着透明代理,手机流量到达8888端口后Charles才会真正介入处理。
4.4 手机安装Charles根证书并设置为系统信任
USB通道上的流量走到了Charles,但Android应用是否信任Charles证书,是决定能不能看到明文的关键。Android 7.0(API 24)开始,系统默认不再信任用户CA证书,只信任系统CA证书。这意味着你从手机浏览器下载安装的Charles证书,只对配置了“信任用户证书”的应用有效。
针对这个问题,分两条路:
方案A:如果你的应用本身允许用户证书(大多数debug包默认信任)
直接通过手机浏览器访问http://chls.pro/ssl下载charles-proxy-ssl-proxying-certificate.pem,然后到系统设置里安装。路径一般是:
设置 -> 安全 -> 更多安全设置 -> 加密与凭据 -> 安装证书 -> CA证书安装完成后在“信任的凭据”里的“用户”标签页能看到Charles证书。
方案B:应用不信任用户证书时
这个最典型的是release包或者某些加固过的SDK,只认系统证书。处理办法是把Charles证书导入到Android系统CA目录。具体操作需要手机能解锁system分区,或者使用Magisk模块方式。这一步需要root或者刷机权限,属于进阶玩法,日常纯开发调试并不一定需要。
我的经验是:对于调试阶段的应用,可以在AndroidManifest里显式声明networkSecurityConfig,允许信任用户证书,这是最省事的方式。如果产品走得是正规release流程,那配合测试包单独处理即可,没必要在实际场景中纠结系统证书的问题。
4.5 开始抓包并解析内容
全部配置完毕,Charles界面里就能看到源源不断的请求。按请求列表从上到下依次看,每个条目可以展开看Headers、JSON Body、Timing。常用操作有几个:
Filter栏输入域名或关键词,快速过滤 双击任意请求,查看完整请求/响应体 右键某个请求,Save Response保存响应内容手机上的App发出的请求,大部分是JSON格式,Charles可以格式化显示,中文也不会乱码,比在服务器日志那边翻半天方便多了。
还有一点要强调:USB方式并不能让App自己把请求指向127.0.0.1:8888,它依赖的是网络代理配置。所以应用内请求如果走的是OkHttp默认配置,它会自动读取系统代理设置。问题是:Android系统代理设置的是WiFi的HTTP代理,USB adb reverse完全绕开了系统代理配置——应用不知道自己走的是代理,它认为自己在直连127.0.0.1:8888。这就好理解了:
大多数App在代码里写死了直连,或者用了自定义的OkHttpClient没有调用proxy设置如果你关了Charles或者没有执行adb reverse,应用一直连不上127.0.0.1:8888,表现是网络请求直接超时失败。这个行为正好能用来反向确认转发是否生效——如果断掉转发后应用网络马上出错,说明转发链路之前是通的。
5. 常见报错与排查技巧实录
5.1 手机死活连不上电脑的adb
插上USB线,adb devices里什么都看不到。这个问题的概率在Windows上偏高,主要原因是Windows的通用ADB驱动不识别某些手机。解决办法:
下载手机品牌官方的USB驱动,或者从设备管理器里手动更新驱动Windows 10以上系统一般能自动匹配,但一些冷门品牌的手机没有内置驱动,需要去官网找。另外,手机锁屏状态下可能不会正常连接adb,先解锁屏幕再插线。有的手机还有“USB调试”和“仅充电模式下允许USB调试”这两个开关,都要打开。
5.2 执行adb reverse报错
报错信息大概是error: device not found或者more than one device。前者是设备没在线,后者是连了多台手机,需要在命令里指定序列号:
adb -s 1234567890abcdef reverse tcp:8888 tcp:8888还有一种特殊情况:一些定制ROM在系统层面对adb reverse做了限制,比如部分老版本的MIUI或者Flyme会遇到reverse执行成功但流量不通的情况。建议换设备或者升级系统版本再试,这个问题跟应用本身没关系。
5.3 Charles上能看到请求,但内容全是乱码
能看到请求条目,说明链路是通的,但内容不可读。原因基本就两个:一是SSL Proxying没开,抓到的只是TCP握手和加密数据;二是手机的Charles证书没有成功安装到用户或系统信任区。先检查SSL Proxying设置,再看手机设置里的证书列表,两个都对上了但还乱码,重启一下Charles和手机连接。
5.4 部分App完全不走代理,抓不到包
这种App多半是做了网络安全策略,或者代码里通过NetworkSecurityPolicy.isCleartextTrafficPermitted()限制了HTTPS代理。解法只能从代码层面入手:把networkSecurityConfig的trust-anchors里加上user证书,具体字符如下:
<network-security-config> <base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="user" /> </trust-anchors> </base-config> </network-security-config>放在App的res/xml目录下,然后在AndroidManifest的application标签里引用android:networkSecurityConfig="@xml/network_security_config"。如果是已经上线的release包,只能通过修改服务器白名单或者抓包机的方式来处理。
5.5 Windows防火墙拦截了Charles代理
Charles启动后第一次作为代理服务接收流量时,Windows防火墙经常会弹窗提示是否允许。如果不小心点了“取消”,之后所有到8888端口的流量都会被防火墙拦掉,表现为Charles界面里什么请求都没有。
处理路径:
控制面板 -> Windows Defender防火墙 -> 允许应用通过防火墙 找到Charles -> 勾选专用和公用 如果列表里没有,手动添加Charles.exe6. 进阶:把USB抓包扩展到其他场景
6.1 抓微信小程序或H5页面的请求
微信开发者工具调试小程序时,可以直接在工具里设置代理。但如果你想抓手机上运行的微信小程序,USB模式同样适用。场景是:微信本身会遵循系统代理,但Android 7+限制用户证书信任,而微信属于比较严格的一类,默认不信任用户CA证书。
有两种主流解决思路:
思路一:手机root后把Charles证书移到系统证书目录 思路二:使用LSPosed加JustTrustMe模块绕过证书校验这两个方案都有一定门槛,不适合普通开发用户。如果是自己的微信小程序在调试阶段,更好的方式是直接用微信开发者工具内置的抓包面板,没必要动真机证书。而如果是排查线上小程序的接口问题,那确实只能靠上述方案。
6.2 同时抓多个设备
adb reverse支持多个设备并行,每个设备执行一次reverse命令,指向同一个8888端口就行。实际用下来Charles能同时显示多台设备的请求,每条请求的Source IP能区分来源。但要注意,多个设备同时跑的时候,Charles界面的请求会混在一起,建议打开Filter或者使用Charles的Recording Settings,按设备维度做一层过滤。
6.3 抓HTTPS/2的流量
Charles 4.x默认支持HTTP/2的解码,不用额外配置。部分新版OkHttp默认开启HTTP/2,这在USB抓包时完全透明,直接看请求头里的HTTP/2.0标记即可。唯一注意点是老版本Charles 3.x对HTTP/2支持不好,建议统一用4.x。
7. 实操心得:USB抓包模式的使用习惯
我个人在实际项目中,已经默认把USB模式当作首选抓包方式,WiFi代理反而变成备用方案了。原因很简单:稳定,干净,不依赖办公室的网络环境。加上现在移动端开发越来越频繁地需要看第三方SDK到底发了什么请求、参数怎么拼的,USB模式可以让我在电脑屏幕前从容地一条一条核对,不用弯腰看手机屏幕上那一小条日志。
有几个使用习惯建议你养出来:
第一,每次插上手机准备抓包,先跑一遍adb reverse,不要想着上一次配过就一直有效。手机重启、adb服务重启、USB线拔插都会导致reverse规则失效。把它当成每次抓包的固定前置动作。
第二,抓到问题包之后,及时在Charles里导出会话文件或者保存响应内容。会话文件可以归档复盘,也方便发给同事分析。文件菜单下File -> Export Session可以导出为.chls文件。
第三,不要把Charles跟Windows上的系统代理混在一起。Charles装完后它有可能会自动修改系统代理设置,让你电脑上浏览器的流量也走它代理。如果你不想让电脑全局流量经过Charles,记得在Proxy Settings里取消勾选Windows Proxy。这个设置项位置很显眼,但很多人忽略了。
第四,真正排查线上问题的时候,建议同时把Charles的请求时间戳和手机端logcat日志对照看,因为有些问题表面上是“请求发失败了”,实际上可能是发起时间、重试策略、缓存策略交织在一起。抓包只能看网络层,配合应用日志才能还原完整链路。
USB模式下Charles的Session列表里会有大量由系统组件发出的请求,有的应用还会在启动时连一些统计域名,这些噪音请求务必学会用Filter栏过滤。我通常的做法是:先什么都不过滤看两分钟,搞清楚流量结构,然后迅速锁定目标域名,再针对性地过滤。这样既有全局感,又不会淹死在噪音里。
这个技巧最终帮助我在客户现场用一根USB线,不依赖客户公司的任何网络策略,半小时内定位到了SDK因为HTTP响应头解析异常导致的内存问题。如果不是USB通道抓包,WiFi方案在那种严格隔离的办公网络里大概率连握手都完成不了。Windows上的USB抓包模式,确实值得每一个Android开发者在工具列表里常驻。