模式二:反向代理扫码 ⭐ 解决 SSL Pinning

适用场景

  • App 启用了 SSL Pinning(证书绑定)
  • 即使安装 CA 证书也无法抓包
  • 想零改动拦截 HTTPS 流量

工作原理

┌────────┐                         ┌────────────┐              ┌────────┐        ┌──────────┐
│  App   │ ──HTTP 明文请求───>     │ 反向代理    │ ──HTTPS──>   │ 抓包   │ ────> │ 真实服务器│
│        │ <──正常返回结果─────    │ 8889 端口  │ <──响应──     │ 服务   │ <──── │          │
└────────┘                         └────────────┘              └────────┘        └──────────┘

App 原本请求 https://uat-tms.example.com/api/...,改为请求 http://<本地IP>:8889/api/...,由沙特协作代为转发到真实服务器。由于中间是 HTTP 明文,可以直接看到请求和响应。

App 端接入步骤

步骤 1:桌面端配置反向代理

打开偏好设置 → 反向代理:

  • 目标服务器 URLhttps://uat-tms.sinopharmlogistics.com
  • 监听端口8889(默认)
  • 启用开关:开启

步骤 2:扫描反向代理二维码

桌面端反向代理配置页面会显示一个专用二维码,扫描后获取:

{
  "shater_url": "http://192.168.31.201:8889",
  "shater_type": "proxy",
  "sessionId": "7a58592c72f04fe"
}

💡 这个二维码和入口码不同。shater_type: "proxy" 告诉 App 把请求基础地址改为 shater_url

步骤 3:App 端修改公共接口路径

只需要改一个地方:App 的 baseURL(或域名配置)。

Android(Retrofit/OkHttp 示例)

// 原来
const val BASE_URL = "https://uat-tms.sinopharmlogistics.com/"

// 改为(指向反向代理)
const val BASE_URL = "http://192.168.31.201:8889/"

// 业务代码完全不用动
interface ApiService {
    @POST("api/user/info")  // 实际请求:http://192.168.31.201:8889/api/user/info
    suspend fun getUserInfo(@Body req: UserReq): UserResp
}

iOS(AFNetworking 示例)

// 原来
NSString *const BASE_URL = @"https://uat-tms.sinopharmlogistics.com";

// 改为(指向反向代理)
NSString *const BASE_URL = @"http://192.168.31.201:8889";

Web/JavaScript

// 原来
const API_BASE = 'https://uat-tms.sinopharmlogistics.com';

// 改为(指向反向代理)
const API_BASE = 'http://192.168.31.201:8889';

⚠️ 改完一个常量,全 App 的接口都走代理。不需要每个接口都改。

步骤 4:桌面端查看拦截记录

App 发起请求后:

  • 左侧"拦截记录"立即出现新记录
  • 中间面板显示完整明文请求和响应
  • 字段提取、二维码识别、报文对比功能全部可用

优势

  • 零 CA 证书(HTTP 明文走代理,HTTPS 由抓包服务处理)
  • 绕过 SSL Pinning(App 不直接访问真实域名)
  • 零业务代码改动(只改 baseURL)

限制

  • ⚠️ 需要在 App 编译时配置 baseURL(无法在不重新打包的情况下切换)
  • ⚠️ 反向代理服务会中继所有请求,可能影响性能
  • ⚠️ 仅 Tauri 模式支持(Web 模式无此功能)

实战技巧

技巧 1:多环境切换

object ApiConfig {
    const val BASE_URL_DEV = "http://192.168.31.201:8889/"     // 本地反向代理
    const val BASE_URL_TEST = "https://uat-tms.example.com/"     // 测试环境
    const val BASE_URL_PROD = "https://tms.example.com/"         // 生产环境
}

打包时通过构建变量切换。

技巧 2:Hosts 配合(无需改 App)

如果你能修改手机的 hosts 文件,直接把域名指向本机 IP:

# /etc/hosts (Android 需要 root,iOS 需要越狱)
192.168.31.201 uat-tms.sinopharmlogistics.com

然后监听 80 端口(需 root),这样 App 不用改一行代码就能走反向代理。

技巧 3:HTTPS 双向验证场景

如果真实服务器使用双向认证(mTLS),反向代理模式不适用。请改用 直接扫码 模式。