第18章 mitmproxy:抓包、改包、脚本化调试
学习目标
- 掌握 mitmproxy 三件套(mitmproxy/mitmweb/mitmdump)与五种工作模式
- 用它拦截、查看、修改 HTTPS 明文流量,做 API 调试与移动端抓包
- 用 Python addon 脚本化改包:自动改请求头、篡改响应、Mock
- 理解它与
tcpdump的分工:一个看应用层明文,一个看字节
前置知识
- 第05章 HTTPS 与 TLS 代理(MITM 原理、CA 信任、HSTS/锁定)
- 第04章 CONNECT、第17章 Squid SSL Bump(同为 MITM)
原理
定位:开发者的 HTTPS 调试神器
第17章 的 SSL Bump 是"企业审计"视角的 MITM;mitmproxy 是**"开发调试"视角的同一技术。它是一个交互式的中间人代理,让你能实时看到、修改、重放** HTTPS 流量——调 API、抓移动端、做安全测试的利器。
三件套
| 工具 | 形态 | 用途 |
|---|---|---|
mitmproxy | 终端 TUI | 交互式查看/拦截,键盘操作 |
mitmweb | 浏览器 Web UI | 可视化,适合不熟终端的人 |
mitmdump | 命令行(类 tcpdump) | 脚本化、自动化、CI |
五种工作模式
regular(默认) :标准正向代理,客户端配 proxy(第01章)
transparent :透明代理,配 iptables 劫持(第11章)
reverse :反向代理,固定转发到某后端(调试线上服务)
upstream :串联到上游代理(代理链)
socks5 :作为 SOCKS5 代理(第06章)
MITM 原理回顾(来自第05章)
mitmproxy 能看 HTTPS 明文,靠的是 第05章 的 MITM:
客户端 ──CONNECT example.com:443──▶ mitmproxy
◀── mitmproxy 用自己的 CA 现签一张 example.com 证书 ──
客户端 ══TLS(信任了 mitm CA)══▶ mitmproxy(解密看明文)══真TLS══▶ example.com
铁律:客户端必须信任 mitmproxy 的 CA(首次运行生成在 ~/.mitmproxy/)。不装 CA 就会证书报错——这正是 第05章 强调的 MITM 安全边界。HSTS 和证书锁定的 App 抓不到,是正常的安全机制。
脚本化:addon 的请求/响应钩子
mitmproxy 用 Python addon 在流量经过时插入逻辑——本质是给代理装"可编程 filter"(呼应 第30章):
# 几个核心钩子,按流量阶段触发
def request(flow): # 请求即将发往服务器前
...
def response(flow): # 响应从服务器返回后
...
flow.request / flow.response 可读可改——改头、改体、改状态码、Mock 整个响应,全在几行 Python 里。
️ 实现 / 命令
实验一:起 mitmproxy 看 HTTPS 明文
mitmproxy --listen-port 8080 # 启动 TUI
# 另一终端:装 CA 后走它(演示用)
curl -x http://127.0.0.1:8080 \
--cacert ~/.mitmproxy/mitmproxy-ca-cert.pem \
https://httpbin.org/get
# mitmproxy 界面里实时出现这条请求,按回车可看完整明文请求/响应
实验二:mitmdump 脚本自动改包
# addon.py —— 给所有请求加一个头,把响应里的 foo 替换成 bar
def request(flow):
flow.request.headers["X-Debug"] = "mitm" # 注入请求头
def response(flow):
if flow.response.text:
flow.response.text = flow.response.text.replace("foo", "bar") # 篡改响应体
mitmdump -s addon.py --listen-port 8080
# 此后所有经过的请求被加头、响应被替换——可用于调试、Mock、注入测试
实验三:Mock 一个接口(不碰真后端)
# 拦截特定路径,直接返回伪造响应,根本不发往后端
from mitmproxy import http
def request(flow):
if flow.request.path == "/api/user":
flow.response = http.Response.make(
200,
b'{"id": 1, "name": "mock-user"}',
{"Content-Type": "application/json"},
)
前端联调时,后端还没好?用这招直接 Mock。
实验四:移动端抓包
# 1. 手机和电脑同一 WiFi;手机 WiFi 代理设为 电脑IP:8080
# 2. 手机浏览器访问 http://mit.it 下载并信任 mitmproxy CA
# 3. mitmweb 在电脑上可视化手机流量
mitmweb --listen-port 8080
# 注意:做了证书锁定的 App(银行/大厂)抓不到——锁定就是为防这个(第05章)
实验五:与 tcpdump 的分工
# tcpdump:看字节流(TLS 是密文,看不懂应用层)
sudo tcpdump -i any -n 'tcp port 443' # 只能看到加密字节
# mitmproxy:看应用层明文(解密后的 HTTP)
mitmproxy --listen-port 8080 # 看到完整 URL/头/体
分工:排查"连不连得通、握手对不对" → tcpdump(第01章 起就在用);排查"请求内容对不对" → mitmproxy。 两者互补。
排错
| 现象 | 根因 | 解决 |
|---|---|---|
certificate problem | 客户端没信任 mitm CA | 装 ~/.mitmproxy/mitmproxy-ca-cert.pem |
| App 流量抓不到 | 证书锁定(第05章) | 锁定无法绕过;用 debug 构建/越狱环境 |
| HSTS 站点失败 | 浏览器对 HSTS 拒绝异常证书 | 设计如此 |
| HTTP/2 流量异常 | 个别老配置 h2 支持问题 | 升级 mitmproxy,或强制 h1 |
| 透明模式不拦截 | 没配 iptables/--mode transparent | 参考 第11章 |
| 改了响应体长度对不上 | 没更新 Content-Length | 改 flow.response.text 时框架会自动算长度,改 raw 要手动 |
本章小结
- mitmproxy 三件套:mitmproxy(TUI) / mitmweb(Web) / mitmdump(脚本),五模式(regular/transparent/reverse/upstream/socks5)。
- 它是"开发调试视角"的 MITM,原理同 第05章:动态签证书 + 客户端信任 CA;HSTS/锁定可反制。
- Python addon 用
request/response钩子脚本化改包、Mock,是可编程代理的轻量形态。 - 与 tcpdump 分工:tcpdump 看字节/握手,mitmproxy 看应用层明文/内容。
下一章 第19章 内网穿透与隧道,换个问题:内网服务没有公网 IP,如何让外部访问?frp、gost、SSH 反向隧道、ngrok 各显神通。