ApiCatcher 实时同步使用文档

把手机上抓到的 HTTP/HTTPS 流量,实时推到电脑或其它系统。

协议规范:Real-time Sync Protocol


1. 功能说明

ApiCatcher 在 iOS 和 Android 上通过 VPN 抓包后,用 WebSocket 把数据流式推到局域网里的接收端。抓包一开始就会推,不用等会话结束再导出文件。

接收端用途配置方式
ApiCatcher Desktop在电脑上看包、分析、回放扫 Desktop 二维码
Burp Suite 扩展进 Burp 做安全测试扫扩展页二维码
自定义接收器接到自己的服务或内部系统ws:// 并测通

同时只能开一种。打开其中一个,另外两个会关掉。


2. 能做什么

在电脑上看包。 大 JSON、长 Header、二进制 Body 在手机上不好看,接到 Desktop 后可以在电脑上解析、对比、回放。

进 Burp Suite。ApiCatcher for Burp Suite Extension,手机抓到的包可以进 Site map 或 Proxy History,再发到 Repeater、Intruder。手机用 VPN 抓包,电脑不用配系统代理。

接到 API 安全检测或 DLP。 测试测 App 时开抓包和实时同步,流量进你们自己的检测平台,扫身份证号、手机号、Token、密钥这类字段,找出可能泄露数据的接口,再出报告发给开发或测试。

根据流量更新 API 文档。 接收器对比历史字段,发现请求或响应里可能新增的字段,再用大模型补用途和注释,邮件通知文档负责人。

给自动化或 Mock 用。 把完整请求存下来,当测试数据,或拿去生成 Mock。


3. 使用前

  1. HTTPS 要解密的话,先安装并完全信任 ApiCatcher 根证书。
  2. 手机和接收端连同一 Wi-Fi。出于数据安全考虑,目前只支持局域网 ws://,不支持 wss://,流量不出局域网。
  3. 电脑或服务器防火墙放行接收端口(例如 8080)。
  4. 先把接收端跑起来,再在 App 里测连通性。

4. 打开实时同步

  1. 打开 ApiCatcher,进抓包首页。
  2. 点右上角「+」。
  3. 选「实时同步」。
  4. 顶部三个页签:Desktop / Burp Suite / 自定义接收器。

打开后,首页会显示「实时同步已开启」,以及接收器在线或离线。点这条提示可以回到设置页。


5. 接到 ApiCatcher Desktop

  1. apicatcher.net 下载并打开 ApiCatcher Desktop。
  2. 在 Desktop 里启动实时同步接收器,屏幕上会出二维码。
  3. 手机打开「实时同步 → Desktop」。
  4. 点「扫描二维码」,扫 Desktop 上的码。
  5. 扫成功后能看到接收器地址和在线状态。
  6. 打开「启用状态」。
  7. 回首页,启动 VPN 抓包,去目标 App 里操作,Desktop 上应该陆续出现请求。

显示离线时,先看 Desktop 还在不在跑、手机和电脑是不是同一网段,再点「重新扫码」。

ApiCatcher Desktop 实时同步接收器


6. 接到 Burp Suite

扩展说明:https://apicatcher.net/zh-CN/burpsuite-extension

  1. 下载扩展 .jar(或自己编译),在 Burp 的 Extensions → Installed → Add 里按 Java 扩展加载。
  2. 打开顶部的 ApiCatcher 标签页,确认 WebSocket 服务已启动;没有的话点 Start Server。
  3. 手机打开「实时同步 → Burp Suite」,扫扩展页上的二维码。
  4. 打开启用开关,再启动抓包。
  5. 默认进 Target → Site map。要看完整请求/响应,把同步目标改到 Proxy → HTTP history。进 History 的请求会带 X-ApiCatcher-RequestId
  6. 之后可以发到 Repeater、Intruder。

同步有问题,到 Extensions → Installed,选中该扩展,看下面的 Output / Errors。

ApiCatcher for Burp Suite 扩展配置


7. 接到自定义接收器

  1. 先在电脑或内网把接收端跑起来(见第 8 节)。地址类似 ws://192.168.1.75:8080
  2. 手机打开「实时同步 → 自定义接收器」。
  3. 「远程连接地址」填 ws://IP:端口。右侧「文档教程」是协议说明。
  4. 点「测试连通性」,成功后地址会保存。
  5. 打开「启用实时推流」。地址为空或测不通,开关开不了。
  6. 改地址后开关会关掉,需要重新测通再开。
  7. 启动抓包,接收端应开始收到 JSON 帧。

不要填 http://wss://。也不要填 127.0.0.1,那是手机自己。


8. 自定义接收器怎么实现协议

规范:README_zh.md
仓库:apicatcher-realtime-sync-protocol
Java SDK:apicatcher-sync-sdk-java

8.1 连接

角色
WebSocket ClientApiCatcher App
WebSocket Server你的接收器
  • 用局域网 ws://(出于数据安全考虑,不支持 wss://,流量不出局域网)
  • 断线后 App 会自己重连
  • 断线期间抓到的数据、传了一半的分片作废,不补发
  • 一条连接上会交叉推多条请求,必须用 requestId 分组

8.2 消息格式

每条都是 JSON Text Frame:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "req_start",
  "timestamp": 1711268370123,
  "payload": {}
}
字段含义
type目前是 http
requestId一条请求的 UUID,分片靠它归组
event见下面几个事件
timestamp毫秒时间戳
payload该事件的数据

8.3 事件

一条请求一般是:

req_start → req_body* → res_start → res_body* → req_end

req_body / res_body 可能没有,也可能有多片。没有 Body 就不会发对应事件。

req_start,请求发出:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "req_start",
  "timestamp": 1711268370123,
  "payload": {
    "url": "https://api.example.com/data",
    "method": "POST",
    "httpVersion": "HTTP/1.1",
    "headers": [{"name": "User-Agent", "value": "ApiCatcher/1.0"}]
  }
}

收到后按 requestId 建一条缓存,记下 URL、方法、请求头。

req_body / res_body,Body 分片:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "res_body",
  "timestamp": 1711268370123,
  "payload": {
    "data": "eyBzdWNjZXNz..."
  }
}

payload.data 是二进制的 Base64。发送是按顺序的,WebSocket 基于 TCP,收到的顺序就是发送顺序。按到达顺序解码再拼接。大 Body 会拆成多片(大约 16KB~32KB),不要等一整包再处理。

res_start,响应头到了:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "res_start",
  "timestamp": 1711268370123,
  "payload": {
    "status": 200,
    "httpVersion": "HTTP/1.1",
    "headers": [{"name": "Content-Type", "value": "application/json"}]
  }
}

req_end,这条请求结束:

{
  "type": "http",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "event": "req_end",
  "timestamp": 1711268370123,
  "payload": {
    "error": null,
    "timings": {
      "send": 0,
      "wait": 150,
      "receive": 5
    }
  }
}
  • errornull 表示正常结束,否则是 "Timeout""Connection Aborted" 这类说明
  • timings 单位毫秒:发送、等待响应、接收响应
  • 收到 req_end 后再拼成完整记录,然后清掉这条缓存
  • WebSocket 断开时,所有还没收到 req_end 的记录都丢掉

8.4 组装

连接建立
  └─ map: requestId → 组装中的请求

收到 JSON 帧
  ├─ req_start  → 新建,写入 url / method / headers
  ├─ req_body   → Base64 解码,追加到请求 Body
  ├─ res_start  → 写入 status / 响应头
  ├─ res_body   → Base64 解码,追加到响应 Body
  └─ req_end    → 写入 error / timings,交给业务,从 map 删掉

连接断开
  └─ 清空 map,半成品不要当完整请求

扫描、入库、更新文档,等 req_end 之后再做。分片阶段 Body 还不完整。

8.5 用 Java SDK

apicatcher-sync-sdk-java 负责 WebSocket 服务和分片组装。一条请求完整后,回调一条 HAR 1.2 entry JSON(不是完整 HAR 文件)。

环境:JDK 11+,Maven 3.x+。

实现监听:

import com.apicatcher.sync.TrafficListener;

public class StandardConsoleListener implements TrafficListener {
    @Override
    public void onTrafficReceived(String harJson) {
        System.out.println("收到一条完整请求:");
        System.out.println(harJson);
    }
}

启动:

import com.apicatcher.sync.ApiCatcherReceiver;

public class App {
    public static void main(String[] args) {
        int port = 8080;
        ApiCatcherReceiver receiver =
            new ApiCatcherReceiver(port, new StandardConsoleListener());
        receiver.start();
        System.out.println("监听端口 " + port);
    }
}

手机填 ws://<这台电脑的局域网 IP>:8080,防火墙放行该端口。

onTrafficReceived 里可以扫敏感字段、和文档做 diff、转给分析服务,或写入消息队列。

8.6 自己解析时注意

  • 只处理 Text Frame,按 requestId 分组
  • Body 按到达顺序拼接,不要按 timestamp 重排
  • 并发请求会交叉推,map 必须按 requestId 隔离
  • 断开连接就清未完成的记录,协议不补传
  • 规范目前是 1.0.0-Draft,遇到不认识的 event 忽略即可,别直接退出

9. 常见用法

抓包做安全检测

  1. 内网接收器先启动
  2. 手机扫码或填 ws://,测通并启用
  3. 启动抓包,按用例操作 App
  4. 平台对完整请求扫敏感字段
  5. 报告发到邮件 / IM,写明 URL、字段、出现在请求头 / Query / Body 哪一段

用流量补文档

  1. 接收器保存每个接口最近几次请求/响应
  2. 按路径 + 方法对比字段
  3. 新增或类型有变的字段,交给大模型生成注释
  4. 整理一份更新清单,邮件给接口负责人

用 Burp 做安全测试

  1. 装扩展,Start Server
  2. App 扫码,启用 Burp 同步
  3. 抓包后在 Site map 看接口,在 History 里挑请求继续测

10. 常见问题

测连通性失败
接收端开了没、IP 是不是这台电脑的局域网地址、端口放行了没、是不是同一网段。不要填 127.0.0.1,不要用 http://

开关开不了
地址不能为空。自定义接收器必须先测通。

首页显示离线,接收端其实在跑
电脑休眠、切了 Wi-Fi、进程退出都会变离线。回设置页看状态,Desktop / Burp 可以重新扫码。

有的请求电脑上看不到
断线期间的包不补发,确认同步开着再抓。过滤规则、域名黑名单也可能让部分流量不走 MITM。

三种接收端能一起开吗
不能。优先级是 Desktop → Burp Suite → 自定义,只连一个。

为什么不直接传一份 HAR
大 Body 在 VPN 进程里打成一个大 JSON 容易内存不够。协议用分片推。Java SDK 会在接收端再拼成 HAR entry。

首页状态一直在转
正在探测 WebSocket。一直没结果的话,查网络和接收端进程。


11. 相关链接