文章首发于: https://feinterview.poetries.top/blog/wireguard-mitmproxy-ios-app-https-capture
做移动端联调,抓包是绕不过去的基本功。Charles / Proxyman 这类工具走的是「手机设 Wi-Fi 代理指向电脑」的老路子,够用,但有两个死穴:一是很多 App 的流量不吃系统 HTTP 代理(尤其是自己管理连接、走 QUIC/WebSocket、或用了非标准端口的),你设了代理它照样绕过去;二是代理一开,手机所有 App 都受影响,还容易和科学上网工具打架。这篇文章换一条更「底层」的路:用 WireGuard 建一条手机到 Mac 的隧道,把手机全部流量(不管走不走系统代理)都逼进这条隧道,再在 Mac 上用 pf 防火墙把 80/443 透明重定向到 mitmproxy,最后靠 mitmproxy 的中间人证书解出 HTTPS 明文。
我最近就是用这套方案抓一台 iPhone 上某交易类 App(Binance 港版)的真机接口,从 Mac 装工具、生成密钥、扫码导入、pf 规则、到手机装证书信任,整条链路又踩了一遍,顺手把每步都记了下来。这篇就以这套实操为线索,把 Mac 端隧道 + 透明代理 和 iOS 端隧道 + 证书信任 两段拆开讲透,让你照着做一次就能通。
在本篇文章中,我们将从浅入深,和大家一起学习以下知识:
WireGuard隧道抓包相比传统Wi-Fi代理抓包强在哪、适合什么场景- 整条链路的数据流长什么样:手机 → 隧道 →
pf重定向 →mitmproxy→ 出网 Mac上怎么装wireguard-tools和mitmproxy(含brew cask装不出 CLI 的坑)- 怎么用
wg genkey生成双端密钥、写wg0.conf/phone.conf、qrencode扫码导入手机 pf规则怎么写才能同时做NAT出网 +80/443重定向到mitmproxy- 为什么透明模式的
mitmweb必须用sudo跑,不然一直报Insufficient privileges - iOS 怎么装
mitmproxy的CA证书,并在「关于本机」里开启完全信任这一步 - 抓不到某个 App 明文时,怎么判断是不是撞上了
SSL Pinning,以及能怎么办 - 怎么把整套抓包沉淀成
Claude Code的SKILL,让 AI 自己起服务、过滤域名、提取接口
# 一、整体架构
先把整条链路画清楚,你就知道每个组件在干嘛、凭证从哪来:
┌─────────────┐ WireGuard 加密隧道 ┌──────────────────────────────────────┐
│ iPhone │ 10.9.0.2 ─────────▶ │ Mac (10.9.0.1) │
│ │ (全流量进隧道 │ │
│ WireGuard │ AllowedIPs=0.0.0.0/0)│ utun (wg 接口) │
│ 已装CA并信任 │ │ │ │
└─────────────┘ │ ▼ pf rdr 80/443 │
│ mitmproxy 透明代理 :8080 │
│ │ (用自己的CA重签,解出明文) │
│ ▼ pf nat 出 en0 │
│ 物理网卡 en0 ───────▶ 互联网 │
│ │
│ mitmweb 界面 :9091 (看/改报文) │
└──────────────────────────────────────┘
@前端进阶之旅: 代码已经复制到剪贴板
三个关键点,理解了就不会瞎调:
- 为什么用隧道而不是
Wi-Fi代理:WireGuard客户端配AllowedIPs = 0.0.0.0/0,意味着手机把所有IP流量都塞进隧道,App 想绕都绕不开(这是隧道相对系统代理最大的优势)。 - 明文是怎么来的:
HTTPS是加密的,mitmproxy做「中间人」——用自己的根证书CA重新签发目标站点证书。手机必须先信任这张CA,加密流量才能被解开,否则你只能看到一堆CONNECT和加密字节。 - 谁来把
80/443交给mitmproxy:靠Mac的pf防火墙做重定向(rdr),其余端口(DNS、WebSocket、直连等)走NAT正常出网。