> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# mitmproxy 完全指南
- URL: https://blog.vercanti.com/mitmproxy-wan-quan-zhi-nan/
- Published: 2026-08-28T14:35:10.000Z
- Updated: 2026-08-28T14:58:12.000Z
- Description: 最后更新：2026-03-31 相关文档：js逆向调试技巧(/js-ni-xiang-diao-shi-ji-qiao/) Frida基础(/frida-ji-chu-zhi-nan/) 反反爬技术汇总(/fan-fan-pa-ji-zhu-hui-zong/) mitmproxy 是一个开源的中间人代理工具，支持拦截、修改、重放 HTTP/HTTPS 流量。 mitmproxy 通过 Python 插件实现自动化处理。 只处理目标域名，减少无关噪声： 未安装证书时，HTTPS 请求会显示为 << Killed 或 SSL Error，需在目标设备安装并
- Author: yellowdog
- Tags: js逆向, 技巧步骤

> 官方文档：<https://docs.mitmproxy.org/>  
> 适用版本：mitmproxy 10.x+（2026-05-08 核实）

最后更新：2026-03-31

相关文档：[js逆向调试技巧](https://blog.vercanti.com/js-ni-xiang-diao-shi-ji-qiao/) [Frida基础](https://blog.vercanti.com/frida-ji-chu-zhi-nan/) [反反爬技术汇总](https://blog.vercanti.com/fan-fan-pa-ji-zhu-hui-zong/)

---

## 1\. 基础概念

### mitmproxy 是什么

mitmproxy 是一个开源的中间人代理工具，支持拦截、修改、重放 HTTP/HTTPS 流量。

| 组件        | 说明            |
| --------- | ------------- |
| mitmproxy | 交互式终端界面（TUI）  |
| mitmweb   | Web 界面，可视化操作  |
| mitmdump  | 命令行脚本模式，可编写插件 |

### 安装

```bash
pip install mitmproxy

# 或下载预编译二进制
# https://mitmproxy.org/downloads/

```

### 证书安装（HTTPS 抓包前提）

```bash
# 1. 启动 mitmproxy
mitmproxy

# 2. 设备配置代理指向 mitmproxy（默认端口 8080）
# 3. 访问 http://mitm.it 下载证书
# 4. 安装证书为受信任根证书

# Android 证书安装（需 root）
adb push ~/.mitmproxy/mitmproxy-ca-cert.pem /sdcard/
# 在手机上：设置 → 安全 → 从存储设备安装证书

# iOS 证书安装
# 访问 http://mitm.it，下载 iOS 证书并信任

```

---

## 2\. 基础使用

### 启动方式

```bash
# 普通代理模式
mitmproxy -p 8080

# Web 界面模式
mitmweb -p 8080

# 脚本模式
mitmdump -s script.py -p 8080

# 透明代理模式（不修改客户端配置，需 iptables 配合）
mitmproxy --mode transparent -p 8080

# 上游代理（mitmproxy → 上游代理 → 目标）
mitmproxy --mode upstream:http://proxy:8888

# SOCKS5 代理模式
mitmproxy --mode socks5 -p 1080

```

### mitmproxy TUI 快捷键

| 按键    | 功能      |
| ----- | ------- |
| Enter | 查看请求详情  |
| q     | 返回上一级   |
| f     | 设置过滤器   |
| i     | 设置拦截规则  |
| a     | 放行拦截的请求 |
| r     | 重放请求    |
| e     | 编辑请求/响应 |
| d     | 删除条目    |
| z     | 清空列表    |
| w     | 保存流量到文件 |

### 过滤语法

```
# 过滤域名
~d example.com

# 过滤 URL 包含关键词
~u api/sign

# 过滤请求方法
~m POST

# 过滤响应状态码
~s 200

# 组合条件
~d example.com & ~u api

# 排除静态资源
~d example.com & !~u \.(js|css|png|jpg|gif)$

```

---

## 3\. 插件开发（核心用法）

mitmproxy 通过 Python 插件实现自动化处理。

### 插件基础结构

```python
# script.py
from mitmproxy import http, ctx

class MyAddon:
    def request(self, flow: http.HTTPFlow) -> None:
        """拦截请求"""
        pass

    def response(self, flow: http.HTTPFlow) -> None:
        """拦截响应"""
        pass

addons = [MyAddon()]

```

### 打印所有请求

```python
from mitmproxy import http

class Logger:
    def request(self, flow: http.HTTPFlow) -> None:
        print(f">> {flow.request.method} {flow.request.pretty_url}")
        if flow.request.content:
            print(f"   Body: {flow.request.content[:200]}")

    def response(self, flow: http.HTTPFlow) -> None:
        print(f"<< {flow.response.status_code} {flow.request.pretty_url}")

addons = [Logger()]

```

### 捕获 API 响应（提取加密参数）

```python
import json
from mitmproxy import http

class ApiCapture:
    def response(self, flow: http.HTTPFlow) -> None:
        # 只处理目标 API
        if "api.example.com" not in flow.request.host:
            return
        if "/sign" not in flow.request.path:
            return

        # 获取请求头（找 sign 参数位置）
        headers = dict(flow.request.headers)
        print("Request Headers:", json.dumps(headers, indent=2))

        # 获取请求体
        try:
            body = json.loads(flow.request.content)
            print("Request Body:", json.dumps(body, indent=2, ensure_ascii=False))
        except Exception:
            print("Request Body (raw):", flow.request.content)

        # 获取响应体
        try:
            resp = json.loads(flow.response.content)
            print("Response:", json.dumps(resp, indent=2, ensure_ascii=False))
        except Exception:
            pass

addons = [ApiCapture()]

```

### 修改请求

```python
from mitmproxy import http

class RequestModifier:
    def request(self, flow: http.HTTPFlow) -> None:
        # 添加/修改请求头
        flow.request.headers["X-Custom-Header"] = "my-value"
        flow.request.headers["Authorization"] = "Bearer fake-token"

        # 修改请求参数
        if flow.request.path.startswith("/api/search"):
            flow.request.query["page"] = "1"

        # 替换请求体（JSON）
        if "application/json" in flow.request.headers.get("content-type", ""):
            import json
            body = json.loads(flow.request.content)
            body["modified"] = True
            flow.request.content = json.dumps(body).encode()

addons = [RequestModifier()]

```

### 修改响应（Mock 接口）

```python
import json
from mitmproxy import http

class ResponseMocker:
    def response(self, flow: http.HTTPFlow) -> None:
        if "/api/list" in flow.request.path:
            # 替换响应体
            mock_data = {"code": 0, "data": [], "total": 0}
            flow.response.content = json.dumps(mock_data).encode()
            flow.response.headers["content-type"] = "application/json"
            flow.response.status_code = 200

addons = [ResponseMocker()]

```

### 重定向请求（本地替换）

```python
from mitmproxy import http

class LocalReplace:
    def request(self, flow: http.HTTPFlow) -> None:
        # 将线上 JS 替换为本地修改版
        if flow.request.path.endswith("/encrypt.js"):
            with open("/tmp/encrypt_patched.js", "rb") as f:
                flow.response = http.Response.make(
                    200,
                    f.read(),
                    {"Content-Type": "application/javascript"},
                )

addons = [LocalReplace()]

```

---

## 4\. 流量保存与重放

```bash
# 保存流量
mitmdump -w traffic.mitm

# 从文件重放
mitmdump -n -r traffic.mitm -s process.py

# 过滤保存
mitmdump -w traffic.mitm "~d target.com & ~m POST"

```

```python
# 从保存文件读取并分析
from mitmproxy.io import FlowReader

with open("traffic.mitm", "rb") as f:
    reader = FlowReader(f)
    for flow in reader.stream():
        print(flow.request.pretty_url)
        print(flow.response.status_code)

```

---

## 5\. 绕过证书检测

### Android SSL Pinning 绕过

```python
# 配合 Frida 使用
# 参见 Frida基础.md 中的 SSL Pinning 绕过章节

# 或使用 apk-mitm 工具自动修改 APK 的 network security config
# pip install apk-mitm
# apk-mitm target.apk

```

### 忽略特定证书错误

```bash
# 允许所有不安全的证书（仅测试用）
mitmproxy --ssl-insecure

```

### 处理双向证书认证（Mutual TLS）

```python
# mitmproxy 支持客户端证书
mitmproxy --client-certs /path/to/client.pem

```

---

## 6\. 实战场景

### 场景 1：自动提取 sign 参数并用 Python 重放

```python
# extract_sign.py
import json
import threading
from mitmproxy import http

captured_requests = []

class SignExtractor:
    def request(self, flow: http.HTTPFlow) -> None:
        if "api.example.com" not in flow.request.host:
            return

        captured_requests.append({
            "url": flow.request.pretty_url,
            "headers": dict(flow.request.headers),
            "body": flow.request.get_text(),
            "timestamp": flow.request.timestamp_start,
        })

addons = [SignExtractor()]

```

### 场景 2：批量修改请求参数

```python
import json
from mitmproxy import http

class BatchModifier:
    """自动翻页采集：修改 page 参数"""
    def __init__(self):
        self.current_page = 1

    def request(self, flow: http.HTTPFlow) -> None:
        if "/api/list" in flow.request.path:
            if "application/json" in flow.request.headers.get("content-type", ""):
                body = json.loads(flow.request.content)
                body["page"] = self.current_page
                flow.request.content = json.dumps(body).encode()

    def response(self, flow: http.HTTPFlow) -> None:
        if "/api/list" in flow.request.path:
            data = json.loads(flow.response.content)
            # 保存数据...
            self.current_page += 1

addons = [BatchModifier()]

```

---

## 7\. 最佳实践

### 精确过滤目标流量

只处理目标域名，减少无关噪声：

```python
TARGET_HOST = "api.example.com"

def request(self, flow: http.HTTPFlow) -> None:
    if flow.request.host != TARGET_HOST:
        return
    # 处理逻辑

```

### 使用 ctx.log 替代 print

```python
from mitmproxy import ctx

ctx.log.info("处理请求")
ctx.log.warn("发现异常")
ctx.log.error("严重错误")

```

---

## 8\. 踩坑与注意事项

### HTTPS 需要安装证书

未安装证书时，HTTPS 请求会显示为 `<< Killed` 或 `SSL Error`，需在目标设备安装并信任 mitmproxy 根证书。

### 响应乱码问题

有些响应是 gzip 压缩的，mitmproxy 自动解压，但手动读 `flow.response.raw_content` 会得到压缩数据，应使用 `flow.response.content`（自动解压）。

### HTTP/2 兼容性

部分服务使用 HTTP/2，可禁用降级到 HTTP/1.1：

```bash
mitmproxy --no-http2

```

### 脚本热重载

修改插件脚本后不需要重启：

```bash
# mitmdump 支持脚本热重载
mitmdump -s script.py
# 在 mitmproxy TUI 中：P → 编辑脚本路径 → 重新加载

```

---

## 最佳实践

**用 `mitmdump` 替代 `mitmproxy` 做批量处理**：`mitmproxy` 需要交互终端，不适合自动化；`mitmdump -s script.py` 可在无头服务器上运行，脚本处理所有流量后直接输出，适合 CI/长期挂载场景。

**addon 脚本用 `response` 钩子而非 `request`**：修改响应内容（如注入 JS、解密响应体）在 `response` 钩子中处理；修改请求头或签名参数在 `request` 钩子中；两个钩子都可以访问完整的请求和响应数据。

**证书信任一次性完成，不要反复安装**：在目标设备安装 mitmproxy CA 证书后，该证书对所有 HTTPS 流量生效；若 SSL Pinning 导致证书被拒，需要配合 Frida 或 objection 绕过固定证书校验。

**用过滤表达式减少噪音**：`mitmproxy -s script.py --filter '~url api.target.com'` 只处理匹配 URL 的流量，避免广告/CDN 流量干扰分析；过滤表达式支持正则、域名、方法、状态码等维度。

**脚本里读取请求体时注意编码**：`flow.request.content` 返回 `bytes`，若请求体是 JSON 用 `flow.request.json()` 直接解析；若是 URL-encoded 用 `flow.request.urlencoded_form` 读取表单字段。

---

## 常见陷阱

### 陷阱：安装证书后 HTTPS 仍然失败

**现象：** 已在设备信任 mitmproxy CA，但 HTTPS 请求仍报证书错误。  
**原因：** App 使用了 SSL Pinning，将服务端证书或公钥硬编码到 App 中，即使系统信任 mitmproxy 证书也会被拒绝。  
**解决：** Android 用 Frida + `ssl-kill-switch2`，iOS 用 `SSL Kill Switch 3` 绕过 Pinning；或 hook App 的证书验证函数让其始终返回成功。

### 陷阱：修改响应后 App 崩溃或显示异常

**现象：** 在 `response` 钩子中修改了响应体，但 App 端崩溃或请求被标记为失败。  
**原因：** 修改了响应体后 `Content-Length` 头还是旧值，导致 App 读取截断；或响应体被签名/校验，修改后校验失败。  
**解决：** 修改 `flow.response.content` 后，mitmproxy 会自动更新 `Content-Length`（调用 `set_content`）；若 App 校验响应签名，还需同时修改签名字段。

### 陷阱：`mitmdump` 脚本异常不显示错误信息

**现象：** 脚本运行但逻辑没有按预期执行，也没有报错。  
**原因：** `mitmdump` 默认吞掉 addon 中未捕获的异常，异常信息只打印到 stderr。  
**解决：** 在脚本中用 `try/except` 包裹并 `print(traceback.format_exc())` 输出；或加 `-v` 参数提高日志详细程度：`mitmdump -v -s script.py`。

---

## 参见

[Frida基础](https://blog.vercanti.com/frida-ji-chu-zhi-nan/)  
[js逆向调试技巧](https://blog.vercanti.com/js-ni-xiang-diao-shi-ji-qiao/)  
[反反爬技术汇总](https://blog.vercanti.com/fan-fan-pa-ji-zhu-hui-zong/)