做接口联调和前后端排障,最难受的不是报错本身,而是看不到完整的请求上下文。客户端到底发了哪些参数、header 里带了什么 token、服务端返回的结构是不是和文档一致,这些信息在浏览器控制台、编辑器日志、服务器 access log 里往往各有一截,拼不全。Mitmweb 就是干这个的——它是 mitmproxy 这个开源网络调试工具配套的 Web 界面组件,启动后所有经过代理的 HTTP/HTTPS 流量都会在浏览器里实时列出来,可以点开看请求头、响应体、cookie、时序,还能直接编辑重发。而 Mitmweb 最容易被低估的部分就是参数配置,启动参数和过滤规则组合好了,调试效率能差出好几倍。这篇就把 Mitmweb 参数配置从头到尾拆开讲,适合正在做接口联调、想抓移动端请求、或者需要持续记录线上流量的开发、测试和运维同学参考。
1. Mitmweb 是什么,在什么场景下才需要折腾参数
1.1 mitmproxy 三兄弟,先搞清 Mitmweb 的定位
mitmproxy 这个项目本身提供了三种形态:命令行交互式的mitmproxy、纯流式处理数据的mitmdump,以及带 Web 界面的mitmweb。三者共用同一个抓包代理内核,差别只在交互层。
命令行版 mitmproxy 是经典的终端 TUI 界面,适合在 SSH 终端里操作,键盘党比较喜欢,但浏览器端这种图形化操作它做不了。mitmdump 更像一个管道工具,通常配合 Python 脚本在后台跑,适合自动化处理流量。Mitmweb 则把全部能力搬到了浏览器里,鼠标点击就能展开请求详情、查看响应预览、搜索过滤,对多数人来说是最没有上手成本的入口。
所以选 Mitmweb 的场景很明确:你不想记一套终端快捷键,不想在手机小屏幕上看抓包结果,或者需要多人通过浏览器同时查看同一份调试数据。它最适合"边看边点"的工作方式。
1.2 需要配置参数的典型场景,从联调到归档
Mitmweb 的参数配置虽然灵活,但不是所有场景都要折腾一遍。下面这几种情况是最典型的:
一是本机接口联调。前后端并行开发时,前端要确认自己发出的请求是不是符合后端的预期,后端要看真实环境里客户端传了什么。把浏览器或者本机服务的代理指到 Mitmweb,过滤掉静态资源请求,剩下的就是目标接口的完整交互记录。
二是移动端/外部设备调试。手机、平板、甚至电视盒子上跑的应用,不方便用抓包客户端时,直接把设备的 Wi-Fi 代理指向安装 Mitmweb 的电脑,然后在电脑浏览器上打开 Mitmweb 界面,设备流量一目了然。这个场景下必须调整监听地址参数,否则设备根本连不进来。
三是持续记录流量用于复盘。接口在特定输入下返回异常,但异常现场不好复现,这时候用-w参数把流量保存成文件,后续用-r参数重新打开分析,比现场手忙脚乱地截图可靠得多。
无论哪种场景,核心都是搞清楚:流量从哪进来、在界面里怎么筛、数据怎么存。这正好对应 Mitmweb 的监听参数、过滤参数和保存参数。
2. 配置参数前先打底:代理原理、证书与安装确认
2.1 代理工作的基本链路,以及为什么会有证书问题
Mitmproxy 本质上是一个中间代理,客户端把请求发给它,它再转发给目标服务器,响应原路返回。在 HTTP 层面这很简单,但到 HTTPS 就有个绕不开的问题:客户端到 Mitmweb 是一段 TLS 连接,Mitmweb 到目标服务器是另一段 TLS 连接。为了让 Mitmweb 能看到明文请求内容,客户端必须信任 Mitmweb 自己的根证书,否则就会报证书校验失败。
理解了这条链路,你就知道为什么参数里会有--ssl-insecure这种看起来"不安全"的开关。它影响的是 Mitmweb 去连接上游目标服务器时的证书校验行为,独立于客户端侧的证书信任。开发环境里目标服务经常用自签名证书,这开关就是用来处理那一层的。
2.2 安装与版本确认,启动前的两个必查项
安装 Mitmweb 不复杂,常见的方式是通过包管理器安装 mitmproxy 全家桶,装完自动带上 mitmweb 命令。在 Python 环境比较干净的情况下,直接安装后就能用。
启动前有两个必查项。第一个是版本,建议跑一下mitmweb --version,确认命令确实可用,也可以顺便看看是新版本还是旧版本,因为不同版本在参数名和行为上有过变动,比如某些--set选项的子选项调整。第二个是端口是否空闲,Mitmweb 默认情况下代理监听 8080,Web 界面监听 8081,如果这两个端口被占用,启动会报错,或者界面打开后不显示流量。检查命令很简单:
# 确认版本 mitmweb --version # 确认端口占用(常见操作系统均可使用) netstat -ano | grep 8080 netstat -ano | grep 8081如果端口被占了,不用先急着杀进程,这正是参数配置要解决的第一个问题:改监听端口。
3. 核心参数逐个拆解:从监听地址到脚本扩展
3.1 监听与 Web 界面参数:决定请求从哪进、界面从哪看
先看一组和"入口"有关的参数,它们是 Mitmweb 参数配置里最基础的部分。
| 参数 | 作用 | 默认值 |
|---|---|---|
--listen-host | 代理服务绑定地址 | 127.0.0.1 |
--listen-port | 代理服务监听端口 | 8080 |
--web-host | Web 界面绑定地址 | 127.0.0.1 |
--web-port | Web 界面监听端口 | 8081 |
--web-open-browser/--no-web-open-browser | 启动时是否自动打开浏览器 | 自动打开 |
默认绑定的127.0.0.1是一个安全选择,只允许本机访问,避免局域网里的其他设备随意扫到你的代理端口。但如果你要抓手机流量,就必须把--listen-host改成0.0.0.0,让设备能从局域网访问进来。同理,--web-host也需要改成0.0.0.0,否则手机本身虽然连上了代理,但你在手机浏览器里还是打不开 Mitmweb 界面。
这里有一个很多人踩过的坑:只改--listen-host不改--web-host,结果手机流量进来了(界面上能看到正在产生新连接),但想在手机上直接看 Mitmweb 界面却打不开。所以做设备调试时,两个地址要一起放开。
--no-web-open-browser也是高频参数。在服务器上跑 Mitmweb 时,自动打开浏览器没有意义,反而可能因为桌面环境没有图形会话而报错。加上这个参数后,你手动访问http://被监听地址:端口即可。
3.2 流量筛选参数:filter / view-filter / hard-filter 的区别
流量一多,界面就容易刷屏。Mitmweb 提供了三个层次的筛选参数,很多人会混淆:
--filter:只影响 Mitmweb 界面显示出来的流量,底层流数据仍然完整保留。--view-filter:和--filter行为类似,同样是在视图层面做筛选。--hard-filter:从源头丢弃不匹配的流,不进入保存文件,不进入界面。
简单理解,前两个是"软过滤",第三个是"硬过滤"。如果你只关心某几个接口,但其他流量又不需要记录,用--hard-filter能显著降低磁盘和内存开销;如果你只是想让界面清爽一点,但后续可能还要翻看其他请求,就用--filter。
筛选表达式是 Mitmproxy 统一的过滤器语法,和界面右上角的搜索框用的是同一套。常用的几类:
~u 正则:按 URL 匹配~m 方法:按请求方法匹配,比如~m POST~h 域名:按主机名匹配~b 正则:按请求体或响应体匹配~q 正则:按查询参数匹配~c 状态码:按响应状态码匹配!取反、&与、|或
举个例子:
# 只显示请求 api 路径并且方法为 POST 的流 mitmweb --filter "~u /api & ~m POST"这个表达式写进命令行参数时,最好用引号包起来,防止特殊字符被终端解释。实际使用中,我习惯先在 Mitmweb 界面的搜索框里验证一遍表达式对不对,再固化到启动参数里,这样调整成本最低。
3.3 数据保存与回放参数,别等流量丢了才想起
有的场景需要把流量留档。比如线上接口出了个偶发问题,你在本地复现了一两次,但不能保证下次还能复现,最好的做法是把每一次排查过程的流量都存下来,回头看时序和参数差异。
保存参数是-w或--save-stream-file,用法如下:
mitmweb -w ./debug_flows.flow运行期间产生的所有流都会被追加写进这个文件。文件格式是 Mitmproxy 专用的 flow 格式,不能用文本编辑器直接看,但可以重新拉回 Mitmweb 界面里查看:
# 读取历史流文件,在浏览器里分析 mitmweb -r ./debug_flows.flow这样打开后,界面里的数据是某个历史时间段的请求,和实时抓包的操作体验一样,可以展开、搜索、查看详情。这里有个细节:-r模式下 Mitmweb 不会监听新流量,它是一个纯查看器。如果需要一边实时抓包一边回放历史,需要另开一个实例,或者把历史文件当成一个独立的数据源来对比。
还有一个容易被忽略的配套参数是--save-stream-file的轮转问题。长时间运行时,flow 文件会越滚越大,文件打开和写入效率都会下降。目前 Mitmweb 参数层没有内置按大小轮转的逻辑,建议在外面套一层定时脚本,按日期生成新文件:
# 按日期生成文件名,避免单个文件无限增大 mitmweb -w "./flows_$(date +%Y%m%d).flow"配合--hard-filter只保留目标流量时,文件增长速度会可控很多。
3.4 代理模式与上游参数,理解 --mode 与 --upstream
Mitmweb 的代理模式由--mode参数控制。默认是regular,也就是作为普通正向代理使用,浏览器或系统设置里手动填代理地址和端口。这种模式最容易理解,也是大多数调试场景的默认选择。
另一个常用模式是transparent,透明模式。透明模式下,Mitmweb 假设请求是由上层网关或 iptables 转进来的,客户端不需要单独配置代理。这个模式在 Linux 环境配合策略路由用得比较多,但配置成本相对高,普通联调一般不碰。
还有两个模式容易和上游混淆:
reverse:反向代理模式,Mitmweb 直接对外暴露一个端口,背后指向某个真实服务。适合你拿一个 URL 直接访问,流量先经过 Mitmweb 再到达目标服务。配置时用--mode reverse:https://目标域名/的方式。upstream:上游代理模式,Mitmweb 本身不是最终出口,它会再把流量转发给另一个代理。配置时配合--upstream指定上游地址。
upstream模式最直接的用途是:客户端访问某个站点,既需要被 Mitmweb 看到明文内容,又需要走公司统一出口代理去访问某些资源。这种模式下参数组合类似:
mitmweb --mode upstream --upstream http://proxy.example.com:8080注意,这里proxy.example.com是一个占位说明,实际你需要填自己的公司代理地址。这个参数组合推高了链路复杂度,所以只在确有必要时才用。
另外两个和连接处理相关的参数值得一并提一下。--ignore-hosts可以让指定域名的流量不被解密,直接放行;--allow-hosts则相反,只对指定域名做代理处理。这两个参数在一些内网地址混合公网地址的环境中非常实用,能在一定程度上减少无谓流量干扰。
3.5 脚本扩展与常用设置参数,让 Mitmweb 更适合你的流程
Mitmweb 参数配置不只限于启动时那几个开关,它还支持通过-s加载 Python 脚本,在请求流经代理时做二次修改。这是 Mitmproxy 家族最有价值的扩展点。
一个典型的扩展脚本可以对请求做动态修改,比如自动补 header、替换响应体、对特定接口做 mock。脚本本身由 Mitmproxy 的接口机制驱动,加载方式在启动参数层面非常简单:
mitmweb -s ./modify_request.py这里不做脚本 API 的深入讲解,但参数层面需要知道两点:一是-s可以多次使用,加载多个脚本,执行顺序按参数顺序;二是脚本加载失败时 Mitmweb 会有启动报错,及时发现比运行中不出流量更省事。
除脚本外,--set参数用来覆盖各种扩展选项,它像一把万能钥匙。比如全局设置项、界面细节、超时控制等,都能通过--set 选项=值传入。几个实用例子:
# 显示更多流量详情 mitmweb --set flow_detail_level=2 # 禁掉 HTTP/2,统一走 HTTP/1.1,方便某些脚本处理 mitmweb --no-http2 # 启动时先禁用缓存,避免调试时拿到缓存数据 mitmweb --anticache--set的具体选项在不同版本之间会有变化,所以依赖某条 set 选项时,建议先查一下当前版本的支持列表。这个参数的使用逻辑不复杂,就是"想改什么先看选项名",不要凭记忆硬写。
4. 适合直接抄的三组配置组合
4.1 本机前后端联调组合
本机联调是最基础的使用方式,目标很明确:只想看到和当前项目相关的接口,过滤掉图片、CSS、JS 这类静态资源。
假设后端接口路径统一带/api,前端联调地址是dev.internal.project,那启动命令可以这么写:
mitmweb --listen-port 8080 --web-port 8081 --filter "~h dev.internal.project & ~u /api" --no-web-open-browser拆解一下:
--listen-port 8080是 Mitmweb 的代理入口,浏览器里把 HTTP 代理配成127.0.0.1:8080。--web-port 8081是 Mitmweb 的界面入口,启动后访问http://127.0.0.1:8081。--filter表达式把"主机名是 dev.internal.project 且路径带 /api"的流转进视图。--no-web-open-browser在这只影响启动时是否自动开浏览器,不涉及功能本身。
浏览器配代理的位置在系统代理设置里,或者用浏览器插件按规则代理。调试的重点是:代理一旦生效,混合了静态资源的流量也都进来了,好的 filter 表达式能帮你省下一大半精力。
如果本地同时起了前端和服务端两个端口,需要注意 Mitmweb 的 8080 不能被占用。遇到端口冲突直接改代理端口:
mitmweb --listen-port 8888 --web-port 80814.2 手机设备接入调试组合
移动端调试时参数配置的重点是监听地址,核心命令如下:
mitmweb --listen-host 0.0.0.0 --listen-port 8888 --web-host 0.0.0.0 --web-port 8081 --no-web-open-browser把--listen-host和--web-host都设成0.0.0.0后,手机和电脑连同一个局域网,手机上把 Wi-Fi 代理指向电脑的局域网IP:8888,流量就会进入 Mitmweb。然后在电脑浏览器或手机浏览器访问http://电脑的局域网IP:8081,就能看到设备流量。
这个组合里最容易出问题的是防火墙。很多系统默认不允许外部设备访问本机的自定义端口,如果手机流量一直进不来,先检查防火墙是否放行了 8888 和 8081 两个端口,再检查代理 IP 是不是填的局域网地址而不是 127.0.0.1。
还有一个证书安装的细节。HTTPS 流量能不能解包看,取决于设备是否信任了 Mitmweb 的根证书。Mitmweb 首次运行时会生成一套证书,设备端需要安装并信任这个根证书。证书安装不是参数配置能代替的,但它是整个调试链路生效的前提,首次设备接入时一定要做。
4.3 持续抓取与离线归档组合
如果目标是记录一段时间的流量,而不是实时盯着界面看,可以这样组合:
mitmweb -w "./flows_$(date +%Y%m%d).flow" --hard-filter "~u /api" --no-web-open-browser-w保存所有通过过滤的流,--hard-filter保证只有目标流量进入保存链路。这里用--hard-filter而不是--filter的原因很简单:既然都打算归档了,没必要把无关流量存下来占空间。
归档文件后续打开的方式:
mitmweb -r ./flows_20250101.flow读取历史文件时,Mitmweb 默认会把文件里的流全部加载进内存,如果文件特别大,打开可能变慢。一个可行的替代方式是配合过滤参数读入,比如只读取某个项目域的流:
mitmweb -r ./flows_20250101.flow --filter "~h dev.internal.project"这样虽然文件本身没变,但界面加载时只按条件展示,操作感受会轻快不少。
5. 常见问题排查与把参数写进配置文件
5.1 高频问题速查表
参数配置过程中踩过的坑,我整理成下面的速查表,可以直接对照处理。
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 启动报端口被占用 | 默认 8080 / 8081 被其他进程占用 | 用--listen-port、--web-port换端口 |
| 本机能访问界面,手机打不开 Web 界面 | 只改了代理监听,没改--web-host | 启动时加--web-host 0.0.0.0 |
| 手机设置了代理但抓不到 HTTPS 明文 | 设备未安装并信任根证书 | 安装证书后重新尝试,检查证书信任开关 |
| 界面流量太多找不到目标请求 | 没有配过滤参数 | 用--filter限制展示内容,或用--hard-filter源头丢弃 |
| 保存的 flow 文件不知道怎么查看 | 不清楚读取参数 | 用mitmweb -r 文件.flow打开 |
| 接口使用自签名证书时报证书错误 | 上游证书校验未关闭 | 测试环境可加--ssl-insecure,生产环境不要这么做 |
| 修改了参数但行为没变化 | 参数被配置文件覆盖,或版本差异 | 检查命令行参数优先级,确认当前 Mitmweb 版本支持的参数名 |
| 界面响应很慢,操作卡顿 | 流数量过大,未做源头过滤 | 使用--hard-filter和--view-filter降低数据量 |
还有一个容易忽略的细节:--filter只影响新进入的流,它不会对当前界面里已经存在的流做二次过滤。如果你启动时没有加 filter,跑了一会儿流量很多了,再发指令要求过滤已经晚了,新的过滤规则只作用于它之后的流。这一点在持续抓包场景里很重要,别等流量爆了才想起加参数。
5.2 用 config.yaml 把常用参数固化下来
命令行参数一次两次用着没问题,但每次启动都要补一长串,或者团队内多人要统一配置时,就不太合适了。Mitmproxy 支持从用户目录下的配置文件读取默认参数,路径是~/.mitmproxy/config.yaml。
配置文件里写的格式很简单,每一行是一个参数名加值:
listen_port: 8080 web_port: 8081 web_open_browser: false filter: "~u /api" ssl_insecure: true这样以后直接执行mitmweb,它就会自动带上这些配置。命令行参数仍然是最优先的,如果配置文件里写了listen_port而某个场景临时要换个端口,直接用--listen-port覆盖即可。
配置文件适合放通用项,比如端口、自动打开浏览器开关、默认过滤规则。而不适合放和具体任务强相关的临时项,比如某个项目特有的域名过滤,这类用命令行参数随用随加更灵活。
我个人在实际操作中的体会是:Mitmweb 参数配置的价值不在单个参数有多复杂,而在你愿不愿意花十几分钟把常用方案沉淀下来。把本机联调、手机调试、离线归档三套命令写进自己的使用笔记或者团队的项目文档,以后每次启动都是复制粘贴的事。真正需要你动脑子的仍然是怎么把过滤表达式写准,以及判断哪些流量值得存档。参数本身只是手段,清晰的工作流才是目的。