mitmproxy 常用 CLI 命令详解
mitmproxy 12.3.1 三形态命令实测详解:mitmdump 四模式/flow 记录回读过滤/HAR 导出/重放/Python 插件、mitmweb 认证与 JSON API、TUI 快捷键,含 pkill 误杀、布尔参数写法、证书链等真实踩坑沉淀。
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"(官方定位语) | 按需处理,适合大流量与无人值守 | 代理四模式、记录/回读/过滤/导出、重放、插件引擎(重点,逐项实测) |
mitmweb | Web 界面(官方标注 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 httpbin | URL 正则匹配 | ✅ 命中 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 做白名单拦截。二者与过滤表达式是不同体系——前者决定"谁被中间人",后者决定"谁被显示/处理"。
九、参考链接
- 软件定位与形态对比:《mitmproxy 介绍与选型指南》
- 安装与 CA 信任实测:《mitmproxy 安装与初始化实战》
- options 与改写参数:《mitmproxy 配置参数详解》
- 官方文档·工具总览与 mitmdump 示例:https://docs.mitmproxy.org/stable/overview-install/ (2026-10-27 查询)
- 官方文档·过滤表达式:https://docs.mitmproxy.org/stable/concepts-filters/ (2026-10-27 查询)
- 官方插件示例库:https://github.com/mitmproxy/mitmproxy/tree/main/examples (2026-10-27 查询)