mitmproxy 常用 CLI 命令详解

mitmproxy 12.3.1 三形态命令实测详解:mitmdump 四模式/flow 记录回读过滤/HAR 导出/重放/Python 插件、mitmweb 认证与 JSON API、TUI 快捷键,含 pkill 误杀、布尔参数写法、证书链等真实踩坑沉淀。

mitmproxymitmproxy抓包调试网络2026/10/27

mitmproxy 常用 CLI 命令详解

目标:把 mitmproxy 12.3.1 三个可执行程序(mitmproxy / mitmweb / mitmdump)的日常命令一次讲透——代理启动与四种模式、flow 文件记录/回读/过滤、HAR 导出、客户端与服务器重放、Python 插件加载与自研示例实测、Web UI 认证访问。全部命令与回显在 Ubuntu 22.04 服务器逐条实测照抄,踩坑过程完整沉淀在注意事项与常见问题中。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(内核 7.0.0-38-generic,x86_64)
  • mitmproxy:12.3.1 binary(官方二进制包,自带 Python 3.15.1 / OpenSSL 4.0.3;安装与 CA 初始化见《mitmproxy 安装与初始化实战》)
  • 实测拓扑:本机 python3 -m http.server 8000 为本地目标站;外网 https://example.com、https://httpbin.org 为远程目标;上游代理链实验使用环境内既有 HTTP 代理 192.168.1.62:7897
  • 实测端口:8080(mitmdump 默认)、8081(mitmweb 代理口)、8082(mitmweb UI 口)、8083(upstream 实验)、8084(HAR 实验)、8085(reverse 实验)、8086(options 改写实验,见《mitmproxy 配置参数详解》)
  • flow 样本文件:/opt/flows/lab.dump(4 条 flow:本地 GET、example.com GET、httpbin POST、httpbin GET,内容见 4.2 节)

二、工具概览

命令形态内存模型本篇覆盖
mitmdump无头命令行,"tcpdump for HTTP"(官方定位语)按需处理,适合大流量与无人值守代理四模式、记录/回读/过滤/导出、重放、插件引擎(重点,逐项实测)
mitmwebWeb 界面(官方标注 beta)全量 flow 进内存启动、认证访问、JSON API 实测
mitmproxy终端全屏 TUI全量 flow 进内存快捷键体系与交互流程(官方文档口径 + 帮助自证)

三者共享同一代理核心与 options 体系,因此本篇的过滤表达式、--set 参数在三形态间通用。

三、前置条件

  • mitmproxy 12.3.1 已安装且 CA 已被客户端信任(curl -x http://127.0.0.1:8080 https://example.com/ 无证书告警,安装篇 8.4-8.5 节);
  • 本地目标就绪:mkdir -p /opt/target && cd /opt/target && echo "hello from local target" > index.html && python3 -m http.server 8000 &;
  • 保留一个前台终端跑 mitmdump,另一个终端发请求(或用 nohup/systemd 常驻,见安装篇第九节)。

四、mitmdump 详解(无头主力)

4.1 启动与监听确认

mitmdump --listen-port 8080

实测回显:

[07:17:35.719] HTTP(S) proxy listening at *:8080.

不加 --listen-port 默认 8080。每条经过的流实时打印一行摘要(请求行 + 响应行):

127.0.0.1:54416: GET http://example.com/
              << 200 OK 577b

客户端侧用 curl 验证链路(HTTP 明文目标直接通):

curl -x http://127.0.0.1:8080 http://127.0.0.1:8000/

实测回显:

hello from local target

4.2 flow 文件记录与回读

启动时挂 -w 把全部流量写为 flow 文件(mitmproxy 私有序列化格式):

mitmdump --listen-port 8080 -w /opt/flows/lab.dump

随后产生四类样本流量(本地 GET、外网 HTTP GET、外网 HTTPS POST、外网 HTTPS GET):

curl -x http://127.0.0.1:8080 http://127.0.0.1:8000/ -o /dev/null
curl -x http://127.0.0.1:8080 http://example.com/ -o /dev/null
curl -x http://127.0.0.1:8080 -X POST -d "user=admin&action=login" https://httpbin.org/post -o /dev/null
curl -x http://127.0.0.1:8080 "https://httpbin.org/get?tool=mitmproxy" -o /dev/null

落盘确认:

ls -la /opt/flows/

实测回显:

-rw-r--r-- 1 root root 20227 Oct 27 07:19 lab.dump

回读(-n 不绑代理端口,-r 读文件):

mitmdump -n -r /opt/flows/lab.dump

实测回显:

127.0.0.1:57912: GET http://127.0.0.1:8000/ HTTP/1.1
     << HTTP/1.0 200 OK 24b
127.0.0.1:57914: GET http://example.com/
              << 200 OK 577b
127.0.0.1:57930: POST https://httpbin.org/post HTTP/2.0
     << HTTP/2.0 200 OK 453b
127.0.0.1:57946: GET https://httpbin.org/get?tool=mitmproxy HTTP/2.0
     << HTTP/2.0 200 OK 297b

注意 HTTP/2 会话在 flow 中的呈现(HTTP/2.0)——协议版本跟随客户端与服务器协商结果。

4.3 过滤表达式(回读与实时过滤通用)

过滤表达式是 mitmproxy 的通用 DSL(TUI 的 f 命令、--set intercept、插件里同一套)。回读实测最直观:

按方法过滤(只看 POST):

mitmdump -n -r /opt/flows/lab.dump "~m POST"

实测回显:

[07:19:23.626] Only processing flows that match "~m POST"
127.0.0.1:57930: POST https://httpbin.org/post HTTP/2.0
     << HTTP/2.0 200 OK 453b

按 URL 子串过滤(~u):

mitmdump -n -r /opt/flows/lab.dump "~u httpbin"

实测回显:

127.0.0.1:57930: POST https://httpbin.org/post HTTP/2.0
     << HTTP/2.0 200 OK 453b
127.0.0.1:57946: GET https://httpbin.org/get?tool=mitmproxy HTTP/2.0
     << HTTP/2.0 200 OK 297b

组合过滤(~c 200 ~m GET,状态码与方法并列即隐式 AND):

mitmdump -n -r /opt/flows/lab.dump "~c 200 ~m GET"

实测回显:

127.0.0.1:57912: GET http://127.0.0.1:8000/ HTTP/1.1
     << HTTP/1.0 200 OK 24b
127.0.0.1:57914: GET http://example.com/
              << 200 OK 577b
127.0.0.1:57946: GET https://httpbin.org/get?tool=mitmproxy HTTP/2.0
     << HTTP/2.0 200 OK 297b

按正文内容过滤(~b,命中 POST 登录体):

mitmdump -n -r /opt/flows/lab.dump "~b user=admin"

实测回显:

127.0.0.1:57930: POST https://httpbin.org/post HTTP/2.0
     << HTTP/2.0 200 OK 453b

常用原子过滤器速查(同一套表达式适用于 -w/-r/TUI/插件):

表达式语义本篇实测
~m POST请求方法✅ 4 条中命中 1 条
~u httpbinURL 正则匹配✅ 命中 2 条
~d example.com域名✅ 见 4.4 节
~c 200响应状态码✅ 与 ~m 组合命中 3 条
~b user=admin请求/响应正文✅ 命中 1 条
~q / ~a只匹配请求阶段 / 响应阶段用于 modify_headers 限定侧别(配置篇 5.4 节实测)
!~m GET取反表达式前缀 !

4.4 输出粒度 flow_detail

--set flow_detail=N(0-3)控制每流的打印详略。flow_detail=1 即 4.2 的单行摘要;flow_detail=3 展开完整头与正文预览,配合域名过滤阅读体验最好:

mitmdump -n -r /opt/flows/lab.dump --set flow_detail=3 "~d example.com"

实测回显(节选):

[07:24:44.893] Only processing flows that match "~d example.com"
127.0.0.1:57914: GET http://example.com/
    Host: example.com
    User-Agent: curl/7.81.0
    Accept: */*
    Proxy-Connection: Keep-Alive

 << 200 OK 577b
    Date: Tue, 27 Oct 2026 07:19:06 GMT
    Content-Type: text/html; charset=utf-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Server: cloudflare
    Last-Modified: Sat, 24 Oct 2026 20:05:47 GMT
    Allow: GET, HEAD
    Accept-Ranges: bytes
    Age: 6
    cf-cache-status: HIT
    CF-RAY: a50fee374ce504ab-HKG
    alt-svc: h3=":443"; ma=86400

    <!doctype html>
    <html lang=en>
    ...

4.5 HAR 导出

--set hardump=<路径> 在进程收到 SIGTERM 退出时把会话写成 HAR 1.2(浏览器 DevTools 通用格式):

mitmdump --listen-port 8084 --set hardump=/opt/flows/lab.har
# (另终端)发两条流量后:
kill -TERM <mitmdump 的 PID>

实测产物:

-rw-r--r-- 1 root root  7698 Oct 27 07:24 lab.har

文件头(实测节选):

{
    "log": {
        "version": "1.2",
        "creator": {
            "name": "mitmproxy",
            "version": "12.3.1",
            "comment": ""
        },
        "pages": [],
        "entries": [

HAR 可直接拖入 Chrome DevTools 的 Network 面板做离线分析,是给"只认浏览器"的同事交付抓包结果的最佳载体。flow 与 HAR 的取舍:flow 保留 mitmproxy 全部元数据、可被 -r 回读重放;HAR 通用但不支持重放。

4.6 上游代理链(upstream 模式)

把 mitmproxy 串在既有代理后面(流量先出上游代理再达目标),排障公司出口或叠加调试时常用:

mitmdump --listen-port 8083 --mode upstream:http://192.168.1.62:7897

实测回显:

[07:23:17.927] HTTP(S) proxy (upstream mode) listening at *:8083.

客户端改指 8083:

curl -x http://127.0.0.1:8083 https://httpbin.org/get -o /dev/null -w "HTTP %{http_code}\n"

实测回显:

HTTP 200

链路证据看 mitmdump 日志尾部——server disconnect 的目标是上游代理而非目标站点,说明会话确实经由 192.168.1.62:7897 转发:

     << HTTP/2.0 200 OK 256b
[07:23:21.620][127.0.0.1:41342] client disconnect
[07:23:21.621][127.0.0.1:41342] server disconnect 192.168.1.62:7897

4.7 反向代理模式(reverse)

不要求客户端配代理,mitmproxy 直接冒充目标服务:

mitmdump --listen-port 8085 --mode reverse:http://127.0.0.1:8000/

实测回显:

[07:25:04.857] reverse proxy to http://127.0.0.1:8000/ listening at *:8085.

客户端把 mitmproxy 当目标访问(完全不感知代理存在):

curl http://127.0.0.1:8085/

实测回显:

hello from local target

reverse 模式对 HTTPS 目标同样适用(--mode reverse:https://目标/),此时客户端侧信任 CA 即可看到发往该服务的全部请求,是"给第三方 Webhook 加观测点"的标准做法。

4.8 Python 插件(-s 脚本引擎)

-s 加载 Python 插件,是 mitmdump 可编程能力的入口。写一个覆盖 request/response 两个事件的最小插件 /opt/addons/add_header.py:

"""实验插件:为所有响应添加自定义头,并拦截对 example.com 的请求改写响应体。"""
import logging
from mitmproxy import http


class AddHeaderAddon:
    def response(self, flow: http.HTTPFlow) -> None:
        flow.response.headers["X-Mitm-Lab"] = "addon-active"
        logging.info(f"[addon] response: {flow.request.method} {flow.request.pretty_url} -> {flow.response.status_code}")

    def request(self, flow: http.HTTPFlow) -> None:
        if flow.request.pretty_host == "httpbin.org":
            flow.request.headers["X-Forwarded-By"] = "mitmproxy-lab"


addons = [AddHeaderAddon()]

要点:文件顶层导出 addons 列表(也可直接写模块级 def request(flow) 函数);request/response 回调在请求到达服务器前/响应返回客户端前触发,flow.request/flow.response 可自由改写。

加载并验证:

mitmdump --listen-port 8080 -s /opt/addons/add_header.py

实测回显(加载日志):

[07:19:58.469] Loading script /opt/share/addons/add_header.py
[07:19:58.470] HTTP(S) proxy listening at *:8080.

发请求并检查响应头:

curl -x http://127.0.0.1:8080 http://example.com/ -o /dev/null -D - | grep -iE "x-mitm-lab|HTTP/"

实测回显:

HTTP/1.1 200 OK
X-Mitm-Lab: addon-active

插件日志同步落盘:

[07:20:01.375] [addon] response: GET http://example.com/ -> 200
[07:20:04.895] [addon] response: GET https://httpbin.org/get -> 200

不写代码的轻量改写用 options 参数即可(modify_headers/modify_body/map_remote,实测见《mitmproxy 配置参数详解》 5.4 节);需要条件逻辑、状态机、外部 IO 时才上插件。

4.9 离线批量变换(-n -r -s -w 组合)

把"回读 + 插件改写 + 再落盘"串成离线管线(官方文档示例同款组合):

mitmdump -n -r /opt/flows/lab.dump -s /opt/addons/add_header.py -w /opt/flows/lab-modified.dump

实测回显:

127.0.0.1:57912: GET http://127.0.0.1:8000/ HTTP/1.1
     << HTTP/1.0 200 OK 24b
127.0.0.1:57914: GET http://example.com/
              << 200 OK 577b
127.0.0.1:57930: POST https://httpbin.org/post HTTP/2.0
     << HTTP/2.0 200 OK 453b
127.0.0.1:57946: GET https://httpbin.org/get?tool=mitmproxy HTTP/2.0
     << HTTP/2.0 200 OK 297b

四条流全部被插件处理并写入新文件。该模式可在不改目标环境的前提下批量修补历史录制(补头、脱敏、改写域名),常用于测试数据准备。

4.10 重放

客户端重放(把录制的请求重新发给服务器):

mitmdump -n -C /opt/flows/lab.dump

-n(不监听)+ -C(client replay)组合离线重放;与 -w 联用可同时记录重放产生的新会话:mitmdump -nC srcfile -w dstfile(官方文档示例)。并发由 --set client_replay_concurrency=N 控制。重放前常用 -w 录制时的过滤器先裁剪样本(如只重放 POST)。

服务器重放(-S,用录制响应伺服客户端)依赖 server_replay_* 参数族微调匹配口径,常用于"录制一次、离线回放给前端"的契约测试场景(参数语义见《mitmproxy 配置参数详解》 5.5 节)。

五、mitmweb 详解(Web 界面)

5.1 启动

mitmweb --listen-port 8081 --web-port 8082 --no-web-open-browser

实测回显(随启动输出):

Web server listening at http://127.0.0.1:8082/
Proxy server listening at *:8081

--listen-port 是代理口(客户端流量入口),--web-port 是管理界面口——两个端口各司其职。无头服务器务必加 --no-web-open-browser(布尔开关取反写法,见 7.2 节排障)。

5.2 认证访问(12.x 新增防护)

12.x 的 mitmweb 默认启用密码防护,无凭证访问管理界面直接 403(实测页面标题 403 Authentication Required)。三种放行方式同实例对比实测:

curl -m 5 "http://127.0.0.1:8082/" -o /dev/null -w "no-auth: HTTP %{http_code}\n"
curl -m 5 "http://127.0.0.1:8082/?token=q1w2e3r4" -o /dev/null -w "token-param: HTTP %{http_code}\n"
curl -m 5 -H "Authorization: Bearer q1w2e3r4" "http://127.0.0.1:8082/" -o /dev/null -w "bearer: HTTP %{http_code}\n"

实测回显:

no-auth: HTTP 403
token-param: HTTP 200
bearer: HTTP 200

密码设定:--set web_password=q1w2e3r4(不设则启动时随机生成,打印在控制台)。浏览器人工访问在登录框输入密码即可。

5.3 代理流量入列与 JSON API

给代理口发流量后,管理界面就能看到;API 化读取 /flows(自动化集成常用):

curl -x http://127.0.0.1:8081 http://example.com/ -o /dev/null
curl -x http://127.0.0.1:8081 http://127.0.0.1:8000/ -o /dev/null
curl -H "Authorization: Bearer q1w2e3r4" "http://127.0.0.1:8082/flows" | python3 -m json.tool | head -24

实测回显(节选):

[
    {
        "id": "c5324560-453c-493b-b379-e177e56d45e7",
        "intercepted": false,
        "is_replay": null,
        "type": "http",
        "modified": false,
        "marked": "",
        "comment": "",
        "timestamp_created": 1793085777.5296953,
        "client_conn": {
            "id": "d1a746b0-5a02-4f99-8105-d58e98db0544",
            "peername": [
                "127.0.0.1",
                59218
            ],
            "sockname": [
                "127.0.0.1",
                8081
            ],

/flows 返回全量 flow 的结构化 JSON(请求、响应、连接元数据),可作为团队自建流量看板的数据源;界面上对应的是 mitmweb 的流列表与详情视图(类 Chrome DevTools 的 Inspector/Flow 视图)。

六、mitmproxy 详解(交互 TUI)

mitmproxy --listen-port 8080 进入终端全屏界面(无头环境仅能记录其命令体系,以下快捷键来自官方文档 mitmproxy 交互指南,2026-10-27 查询;界面内随时按 ? 可调出与当前屏上下文相关的帮助,这是官方内置的自证入口):

按键作用说明
?上下文帮助任何屏可用,官方首推的入门入口
k/j 或方向键上下移动选流vim 风格
Enter进入流详情依次查看 Request/Response/Detail 标签页
Tab / h/l详情内切换标签请求与响应切换
f设置过滤表达式与 4.3 节同一套 DSL,如 ~u httpbin
i设置拦截表达式命中的流暂停等待放行
a放行当前拦截流A 放行全部
e编辑流按提示选编辑对象(method/url/header/body…)
r重放当前请求单流级 client replay
w保存所选流输入 flow 文件路径
b保存响应正文导出 body 到文件
z清空流列表与缓冲释放内存(全量流常驻内存)
q返回/退出两级退出

与 mitmdump 的分工:TUI 强在"人在回路"——现场盯着流量、随手改包放行、逐条审视;无人值守、长时大流量则交给 mitmdump。两者共享过滤表达式与插件体系,切换成本几乎为零。

七、注意事项

  • 内存模型决定选型:mitmproxy/mitmweb 全量流进内存,官方定位「适合小样本」;长时抓包、大吞吐场景一律 mitmdump + -w 落盘,超大响应配合 --set stream_large_bodies=3m 转流式。
  • pkill -f 会误杀自身:pkill -f "mitmdump --listen-port" 会把命令行里含同串的当前 shell 一起杀掉(本篇实测过程两次触发,进程退出码 143)。停 mitmproxy 用精确进程名匹配:pkill -x mitmdump、pkill -x mitmweb,或 systemd 场景直接 systemctl stop mitmdump。
  • 布尔参数写法有版本风格:12.x 的命令行布尔开关是「--开关名 开 / --no-开关名 关」的成对形式,传 --web-open-browser false 会报 unrecognized arguments: false(实测踩坑,见 7.2 节)。
  • HTTPS 明文可见的前提是信任 CA:所有"看不到 HTTPS 内容"的问题先查客户端信任链,安装篇 8.3-8.5 节有完整复现与解除实测。
  • flow 文件与 HAR 不可互替:flow 保元数据可重放,HAR 通用只读;需要重放回归的录制一律 flow。
  • upstream/reverse 模式的日志是排障第一现场:server connect/disconnect 行显示真实对端,链路是否按预期走代理/目标,以此行为准。

八、常见问题(FAQ)

Q1:HTTPS 请求经代理后 curl 报 (60) SSL certificate problem? 中间人代理的正常表现:mitmproxy 用自签 CA 动态签发了目标站点证书,客户端不认。两条路:临时 curl -k 跳过校验;根治则把 ~/.mitmproxy/mitmproxy-ca-cert.pem 装入系统信任库(安装篇 8.4 节实测,update-ca-certificates 后同请求 HTTP 200)。浏览器访问 http://mitm.it 可按平台下载证书(onboarding 内置站点)。

Q2:流量挂了上游代理后出网失败? 确认三件事:上游本身可达(curl -x http://上游:端口 https://目标 直测)、--mode upstream:http://上游:端口 写法完整、mitmdump 日志 server disconnect 是否指向上游。本篇 4.6 节实测:日志里出现 server disconnect 192.168.1.62:7897 即代表链路经上游成立;若显示目标站点地址则 upstream 模式未生效,检查 --mode 拼写。

Q3:mitmweb 管理界面打不开 / 403? 连接被拒先查 web_port 与 web_host(默认 127.0.0.1 只听本机,远程访问需 --set web_host=0.0.0.0);403 是 12.x 密码防护,带 ?token=<密码> 或 Bearer 头访问(5.2 节三种方式实测)。远程暴露时务必防火墙限源。

Q4:nohup mitmdump > log 日志是空的? Python 进程 stdout 全缓冲,nohup 落盘的横幅可能迟迟不出现(实测 stdbuf/PYTHONUNBUFFERED 均未必即时)。无头环境验证进程状态改用旁路证据:curl -x http://127.0.0.1:8080 是否通、ps -ef | grep mitmdump 是否在、systemd 场景直接 journalctl -u mitmdump -f 看日志。

Q5:apt 装的 mitmproxy 命令行为和文档对不上? Ubuntu 22.04 源内版本为 6.0.2-1(2021 年),与 12.x 在参数与插件 API 上有代差。mitmproxy --version 先对版本,生产环境按安装篇方案 A 重装 12.3.1。

Q6:想只拦截部分域名,其余直通? --set ignore_hosts='["regex"]' 让匹配连接走纯隧道不解密(对证书固定的 App 必备);反之 allow_hosts 做白名单拦截。二者与过滤表达式是不同体系——前者决定"谁被中间人",后者决定"谁被显示/处理"。

九、参考链接