从抓到改:ProxyPin 抓包工具的 5 个实战用法
【免费下载链接】network_proxy_flutterOpen source free capture HTTP(S) traffic software ProxyPin, supporting full platform systems项目地址: https://gitcode.com/GitHub_Trending/ne/network_proxy_flutter
手机上的接口返回 400,你换到浏览器里发同样的请求,却是 200。浏览器控制台帮不上忙——那台手机根本没连上你的调试环境,请求到底长什么样、差在哪个头,全靠猜。ProxyPin 就是为此做的:一个开源免费的 HTTP(S) 抓包与调试工具,基于 Flutter 开发,Windows、macOS、Linux、Android、iOS 都能跑,同一套工具把抓包、改包、回包串起来。
5 分钟跑起来:从克隆到看到第一个请求
先把环境跑通,不求甚解:
git clone https://gitcode.com/GitHub_Trending/ne/network_proxy_flutter cd network_proxy_flutter flutter pub get然后启动应用,以 Windows 为例:
flutter run -d windowsmacOS 上直接运行编译产物即可,首次打开如果提示不受信任开发者,去「系统设置 → 隐私与安全性」里允许一下。
你会看到什么:主界面是一个按时间排下来的请求列表,点任意一条,能看到完整 URL、方法、状态码、请求头、响应头和响应体。让浏览器随便访问几个站点,列表就开始滚动。这一步不用关心原理,先看到第一条请求再说。
它到底能帮你做什么:5 个核心能力拆解
ProxyPin 的调试动作可以归纳成 5 类,每类都对应项目里一个真实模块,想看实现时可以直接定位:
| 能力 | 场景一句话 | 对应源码 |
|---|---|---|
| 抓包与过滤 | 只看指定域名的流量,其余不拦不显 | lib/network/components/manager/hosts_manager.dart |
| 请求/响应改写 | 改请求头、替换响应报文,不用动应用代码 | lib/ui/desktop/setting/request_rewrite.dart |
| 请求映射(本地 Mock) | 请求根本不发出去,由本地内容或脚本响应 | lib/ui/desktop/setting/request_map.dart |
| AES 响应解密 | 配一个密钥,密文响应体自动还原成明文 | lib/ui/desktop/setting/request_crypto.dart |
| 请求屏蔽 | 按 URL 拦下请求,不让它到服务器 | lib/network/components/manager/request_block_manager.dart |
这 5 类动作覆盖了日常抓包调试的绝大部分需求:先过滤出你关心的流量,改不动应用代码就在中间改请求,后端没就绪就用本地数据顶上,遇到密文响应解开看,不想要的噪音请求直接拦掉。
三个抓包工作流
工作流A:排查只在特定机型上出现的接口异常
后端同学说"我们接口没问题",但你手上这台旧安卓就是复现失败。别急着改代码,先证明问题出在请求侧:在过滤栏只保留目标接口域名,把无关流量全部挡在视野外;再写一个脚本,把请求头里的设备标识改成目标机型的值,反复重放同一个请求,直到复现 400。
脚本入口在 lib/ui/desktop/setting/script.dart,模板里的 API 很简单:
async function onRequest(context, request) { request.headers["X-Device-Type"] = "old_pixel3"; return request; }容易踩的坑:脚本的匹配规则如果写得过宽,会命中其他接口的同名请求头,把问题改得更难看懂。把 URL 匹配条件收到具体接口路径再启用。
跑一轮之后你会看到:列表里这条请求的"已修改"标记亮起来,响应体从 400 变 200——设备标识就是元凶,证据链齐了,可以甩给后端。
工作流B:把线上接口流量切到本地 Mock 联调
后端还在重构支付接口,你不想等他,也不想动真接口。做法是:让发往api.example.com的请求,由你本地的 Mock 服务直接响应。
npm run mock # 起本地mock,监听 3000 端口然后在脚本里接管响应(同样在脚本管理页,lib/ui/desktop/setting/script.dart):
async function onResponse(context, request, response) { response.body = await fetch('http://localhost:3000' + new URL(request.url).pathname).then(r => r.text()); return response; }容易踩的坑:本地服务没起来时脚本不会报错,只会返回空响应,你容易误判成"接口挂了"。先 curl 一下 3000 端口确认活着。
保存后刷新 App,支付页数据立刻来自你的 Mock。想试"余额不足""超时"这些分支,改本地返回就行,不用等任何人。
工作流C:同时盯住 Web 端和移动端两条请求链路
同一个功能,网页上正常,手机上白屏。两条链路分属两台设备,靠人肉记下来对比是不可能的。ProxyPin 的解法是扫码连接:手机端 App 里扫一下电脑端生成的二维码,手机流量就转发到桌面端的抓包界面,不需要手动配 Wi-Fi 代理,配置也会同步过去。
容易踩的坑:扫码连接依赖同一局域网。公司网如果做了 AP 隔离(设备之间互相不通),换到手机热点上再试,问题往往当场解决。
在桌面端打开设备筛选,两条链路的请求按时间交替排列。把同一时刻的两条请求并排看请求头,大概率能发现手机端少了某个关键字段——问题定位到这一步,剩下的就是改 App 代码了。
进阶技巧与隐藏用法
📌 我后来发现onResponse里也能用fetch拉远端数据,不只是改字符串。想把响应体整体替换成另一个环境的真实返回、或者做字段级 diff,全靠这一招,不用碰应用代码。
🔍 脚本调试时别干瞪着结果猜。console.log输出会进到脚本日志里,写复杂逻辑之前先打两行关键变量,能省掉大量来回试错。URL 匹配支持通配和正则,但通配范围一定要收敛——我见过把*一开、全站的请求头都被改了一遍的事故。
还有个不太显眼的入口:环境切换。你可以把 token、环境标识这类值存成环境变量,联调时在桌面端工具栏一键切环境,同一份请求自动带上新值。重复改请求头的场景基本都被它吃掉了。
踩坑记录
有人问过:抓 HTTPS 请求,列表里有条目,但响应体全是乱码或者干脆连接失败。原因是代理证书没装或没被信任。项目里assets/certs/ca.crt就是它自己的 CA,装进系统钥匙串(移动端在设置里信任企业证书)之后,HTTPS 流量才能正常解密展示。证书装一半的状态最坑——连接成功但解不开,别怀疑流量本身。
还有人问:手机扫码连上了,请求列表却死活没有新条目。现象看着像 Bug,实际九成是网络问题:手机和电脑不在同一网段,或者公司 Wi-Fi 开了 AP 隔离。先把两台设备挂到同一个能互 ping 通的网里再抓,别在软件设置里反复折腾。
弱网模拟玩完记得关。开着它复现了一个超时问题,然后忘了关,接下来一小时的请求全部"莫名变慢",自己先把自己绕进去了。模拟类开关用完随手归位,是老手和新手最直观的区别之一。
下一步 & 资源
想继续深入,从这三个地方进:README_CN.md 有完整的特性清单和首次运行注意事项;assets/js/ 目录下放着项目自带的脚本示例,可以直接抄来改;lib/l10n/ 是界面多语言文案,顺手能看到支持的全部语言。遇到行为跟预期对不上的地方,直接去仓库的 Issue 区提,附上你抓到的那条请求,回复通常很快。把抓包、改包、回包放进同一套工具链里,下次再遇到"只有某台设备复现"的问题,你大概只用一杯咖啡的时间。
【免费下载链接】network_proxy_flutterOpen source free capture HTTP(S) traffic software ProxyPin, supporting full platform systems项目地址: https://gitcode.com/GitHub_Trending/ne/network_proxy_flutter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考