mitmproxy — SSL/TLS 拦截代理系统
mitmproxy 是一套交互式 SSL/TLS 拦截代理工具集,支持 HTTP/1、HTTP/2、WebSocket 和 HTTP/3。 它的名字 MITM 来自 Man-In-The-Middle——通过成为客户端信任的证书颁发机构(CA), 对加密 TLS 流量进行透明解密、检查和修改。 项目纯 Python 实现,由 R0CKER / Aldo Cortesi 主导开发。
| 仓库 | github.com/mitmproxy/mitmproxy |
|---|---|
| 官网 | mitmproxy.org |
| 许可证 | MIT |
| 技术栈 | Python 3.10+, asyncio(单线程异步) |
| 安装 | pip / pipx / brew / 独立二进制 / Docker |
1. 概述
mitmproxy 本质上是一个代理服务器(Proxy Server),位于客户端和服务器之间, 能查看、记录、修改双向的 HTTP(S) 流量。与普通 HTTP 代理不同,mitmproxy 通过动态生成拦截证书 来解密 HTTPS 流量,让开发者能像查看明文 HTTP 一样分析加密通信。
三大前端工具
- mitmproxy — 交互式终端(TUI)界面,适合手动分析小批量流量
- mitmweb — Web 图形界面,在浏览器中操作,当前 Beta 状态
- mitmdump — 命令行版本,类似 tcpdump for HTTP,适合脚本化和自动化
mitmproxy.proxy),
只是提供了不同的用户界面。切换工具不影响功能和配置。
核心能力
- 拦截修改 — 实时查看和修改 HTTP/HTTPS 请求与响应
- 重放 — 记录完整 HTTP 会话,支持客户端回放和服务端回放
- 脚本扩展 — 用 Python Addon 系统编程控制代理行为
- 多种代理模式 — 显式代理、透明代理、反向代理、WireGuard、SOCKS5
- TLS 破解 — 内置 CA,动态生成拦截证书,支持 SNI 和 SAN
- 协议支持 — HTTP/1.x, HTTP/2, HTTP/3 (QUIC), WebSocket, DNS, TCP/UDP/DTLS
2. 行为分析(做什么)
以下从行为视角分析 mitmproxy 的功能边界与核心流程。
2.1 用例图 — 角色与功能全景
展示三类主要角色与 mitmproxy 系统的交互边界。
2.2 活动图 — HTTPS 拦截完整流程
从客户端 CONNECT 到最终请求转发的完整活动链,展示 mitmproxy 核心的 MITM 过程。
2.3 序列图 — 透明 HTTPS 拦截时序
展示透明代理模式下最复杂场景的完整交互时序:网络层重定向 + TLS MITM。
2.4 状态机图 — TLS 拦截连接生命周期
展示 mitmproxy 处理一条 TLS 连接时的完整状态转换:从客户端连接建立到请求转发。
3. 结构分析(由什么组成)
以下从结构视角分析 mitmproxy 的组件架构与核心抽象。
3.1 组件图 — 系统宏观架构
展示 mitmproxy 的前端工具、核心引擎与协议层的分层组件架构。
3.2 概念类图 — 核心抽象与关系
展示 mitmproxy 中关键概念实体及其关系。
3.3 部署图 — 典型部署拓扑
展示 mitmproxy 在不同场景下的部署节点拓扑关系。
4. 配置示例与 Demo
4.1 安装
# macOS
brew install mitmproxy
# pip
pip install mitmproxy
# pipx(推荐隔离安装)
pipx install mitmproxy
# Docker
docker run --rm -it -p 8080:8080 mitmproxy/mitmproxy
# 验证安装
mitmproxy --version
4.2 显式代理模式
最基础的使用方式:客户端配置 HTTP 代理后,mitmproxy 直接拦截 HTTPS。
# 启动(默认监听 localhost:8080)
mitmweb
# 客户端配置(以 curl 为例)
curl -x http://localhost:8080 https://example.com
# 指定监听地址与端口
mitmproxy --listen-host 0.0.0.0 -p 8888
首次启动后,按流程安装 CA 证书:
# 1. 代理配置好后,浏览器访问
# http://mitm.it —— 下载对应平台的证书
# 2. 或手动安装:
# macOS: sudo security add-trusted-cert -d -p ssl -p basic \
# -k /Library/Keychains/System.keychain ~/.mitmproxy/mitmproxy-ca-cert.pem
# Linux: cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy.crt
# sudo update-ca-certificates
4.3 透明代理模式
无需客户端配置代理,通过网络层重定向所有流量到 mitmproxy。
# macOS 透明代理
sudo sysctl -w net.inet.ip.forwarding=1
# 将端口 80/443 流量重定向到 mitmproxy 的 8080
echo "rdr pass on en0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080" | sudo pfctl -evf -
echo "rdr pass on en0 inet proto tcp from any to any port 443 -> 127.0.0.1 port 8080" | sudo pfctl -evf -
# 启动
mitmproxy --mode transparent
# Linux (iptables)
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
4.4 反向代理模式
mitmproxy 放在服务器前端,拦截进出流量。
# 反代到指定上游
mitmdump --mode reverse:https://api.example.com
# HTTP 上游
mitmproxy --mode reverse:http://localhost:3000
# 自定义端口
mitmdump --mode reverse:https://example.com@8443
# TCP/TLS 原始代理
mitmdump --mode reverse:tls://example.com:443
mitmdump --mode reverse:dns://8.8.8.8
4.5 Addon 脚本示例
示例 1:给所有响应添加自定义 Header
# add_header.py
def response(flow):
flow.response.headers["X-Proxy"] = "mitmproxy"
# 使用:mitmproxy -s add_header.py
示例 2:将指定域名的请求重定向到本地
# redirect.py
from mitmproxy import http
def request(flow: http.HTTPFlow) -> None:
if flow.request.pretty_host == "api.example.com":
flow.request.host = "localhost"
flow.request.port = 3000
示例 3:计数器 Addon(完整类结构)
import logging
class Counter:
def __init__(self):
self.num = 0
def request(self, flow):
self.num += 1
logging.info(f"We've seen {self.num} flows")
addons = [Counter()]
示例 4:拦截并发起异步 HTTP 调用
from mitmproxy import ctx, http
import aiohttp
async def request(flow: http.HTTPFlow) -> None:
async with aiohttp.ClientSession() as session:
async with session.get("https://check.example.com/api") as resp:
result = await resp.json()
ctx.log.info(f"Check result: {result}")
Addon 脚本热加载:修改并保存 -s script.py 文件后,mitmproxy 自动重新导入,无需重启。
4.6 过滤表达式示例
# 只看 example.com 域名的流量
mitmproxy -p 8080 "example.com"
# 只看 POST 请求
mitmproxy "~m POST"
# 只看 4xx/5xx 响应
mitmproxy "~c 4" "~c 5"
# 只看响应中包含 JSON 的
mitmproxy "~ts application/json"
# 组合:POST 请求 且 example.com 域名
mitmproxy "~m POST & example.com"
# 排除 CSS/JS/图片 等静态资源
mitmproxy "!(~a)"
# 标记并重放
mitmdump -nr infile -w outfile "~m post"
# 标记特定 flow 便于后续操作
# 在 TUI 中使用 :mark
5. 实战速查手册
5.1 工具对比与启动
| 工具 | 界面 | 适用场景 | 流量存储 |
|---|---|---|---|
mitmproxy |
终端 TUI | 手动分析、少量交互 | 内存 |
mitmweb |
Web 浏览器 | 可视化分析、新手友好 | 内存 |
mitmdump |
命令行 | 脚本化、自动化、录制重放 | 流式/文件 |
# 基本启动
mitmproxy # 终端 TUI,默认 8080
mitmweb # Web 界面
mitmdump # 命令行模式
# 保存和读取流量
mitmdump -w outfile # 保存所有流量到 outfile
mitmdump -r infile # 读取并分析已保存的流量
mitmdump -nr infile -w outfile "~m post" # 过滤重放
5.2 代理模式速查
| 模式 | 命令 | 说明 |
|---|---|---|
| 显式代理(默认) | mitmproxy | 客户端需配置 HTTP 代理 |
| 透明代理 | mitmproxy --mode transparent | 网络层重定向,需 iptables/pf |
| 反向代理 | mitmdump --mode reverse:https://x.com | mitm 在服务器前 |
| 上游代理 | mitmdump --mode upstream:http://x:8081 | 链式代理 |
| SOCKS5 | mitmdump --mode socks5 | SOCKS5 服务器 |
| WireGuard | mitmweb --mode wireguard | VPN 模式,适合移动设备 |
| Local Capture | mitmproxy --mode local | 拦截本机应用(eBPF) |
| TUN | sudo mitmdump --mode tun | 虚拟网卡模式 |
| DNS | mitmdump --mode dns | DNS 服务器 (端口 53) |
5.3 过滤表达式速查
| 表达式 | 含义 |
|---|---|
~u regex | 按 URL 过滤 |
~d regex | 按域名过滤 |
~m regex | 按 HTTP 方法过滤 |
~c int | 按响应状态码过滤 |
~b regex | 按请求/响应 Body 过滤 |
~bq regex | 按请求 Body 过滤 |
~bs regex | 按响应 Body 过滤 |
~h regex | 按 Header(name: value) 过滤 |
~hq regex | 按请求 Header 过滤 |
~hs regex | 按响应 Header 过滤 |
~t regex | 按 Content-Type 过滤 |
~a | 匹配静态资源(CSS/JS/images/fonts) |
~q | 仅有请求(无响应) |
~s | 有响应的请求 |
~http / ~tcp / ~dns / ~websocket / ~udp | 按协议过滤 |
~marked | 已标记的 flow |
~e | 匹配错误 |
! | 取反 |
& | 与 |
| | 或 |
5.4 关键 Addon 事件
| 事件 | 触发时机 | 签名 |
|---|---|---|
request | 客户端请求到达 | def request(flow: HTTPFlow) |
requestheaders | 请求头(无 body 时)已接收 | def requestheaders(flow: HTTPFlow) |
response | 服务器响应到达 | def response(flow: HTTPFlow) |
responseheaders | 响应头(无 body 时)已接收 | def responseheaders(flow: HTTPFlow) |
error | 发生错误 | def error(flow: HTTPFlow) |
websocket_message | WebSocket 消息到达 | def websocket_message(flow: HTTPFlow) |
tcp_message | TCP 消息到达 | def tcp_message(flow: TCPFlow) |
running | mitmproxy 启动完成 | def running() |
done | mitmproxy 即将关闭 | def done() |
configure | 配置更新时 | def configure(updated) |
5.5 证书管理
| 文件 | 路径 | 用途 |
|---|---|---|
| CA 私钥 + 证书 | ~/.mitmproxy/mitmproxy-ca.pem | CA 完整密钥对 |
| CA 证书 | ~/.mitmproxy/mitmproxy-ca-cert.pem | 分发到非 Windows 设备 |
| PKCS12 证书 | ~/.mitmproxy/mitmproxy-ca-cert.p12 | Windows 使用 |
| CER 证书 | ~/.mitmproxy/mitmproxy-ca-cert.cer | Android 使用 |
# 首次运行时自动生成 CA
# 查看 CA 信息
openssl x509 -noout -text -in ~/.mitmproxy/mitmproxy-ca.pem
# 使用自定义 CA
mitmproxy --set confdir=/path/to/my-ca-dir
# 使用自定义服务器证书
mitmproxy --certs *.example.com=cert.pem
5.6 常用选项
-p, --listen-port PORT # 监听端口(默认 8080)
--listen-host HOST # 监听地址(默认 localhost)
-s, --scripts SCRIPT # 加载 Python Addon 脚本
--mode MODE # 代理模式
-r, --read-flows FILE # 读取已保存的 flows
-w, --save-stream-file FILE # 保存 flows 到文件
--set option=value # 设置选项
--ignore-hosts HOSTS # 忽略的域名(不拦截)
--tcp-hosts HOSTS # 以 TCP 模式代理的域名
--certs DOMAIN=FILE # 使用自定义证书
http://mitm.it,
按平台指引下载并安装 CA 证书。Android/iOS 安装后还需启用信任(设置→关于→证书信任设置)。