
简介这是一份基于FiddlerCore的C#抓包工具源码面向需要拦截HTTP/HTTPS会话、解析网络请求的Windows开发者尤其适合在无商业授权条件下快速搭建自有抓包环境。资源采用zip压缩包格式共33个文件核心包含11个C#源文件实现代理启动、证书配置、会话事件处理等逻辑、4个DLL运行库与4个可执行程序辅以config配置、pdb调试符号及xml说明等整个包仅717KB结构紧凑。附件中提供两种抓取Session的方式一种是通过系统代理另一种是通过自定义代理WebProxy.Start(8877)并在代码中标注了系统代理设置的位置便于直接修改复用。目前已有1578人学习下载从代码思路、证书签署到FiddlerCore事件挂接均有完整呈现可帮助读者省去四处搜集资料和逆向调试的时间快速理解抓包原理并扩展为自己的工具。1. FiddlerCore抓包不是套壳Fiddler而是把“中间人”请进你的程序在定位线上接口问题时我们常遇到一种尴尬手机和客户端都是好的偏偏服务端日志看不出异常抓包工具又只能手动点按键。FiddlerCore 就是为这个场景准备的——它把抓包引擎的核心能力封装成库让开发者在自己写的程序里直接启动一个 HTTPS 解密代理从而自动捕获进出应用的 HTTP/HTTPS 流量。它能解决的不只是“看流量”而是把“捕获、解密、改写、转发”全部写进自动化流程里适合做接口回归、客户端联调、灰度校验和流量分析工具的从业者。本文不介绍界面操作而是直接讨论如何在代码里落地 FiddlerCore从原理讲到参数再把常见的坑一个个拆开。2. 先搞懂 FiddlerCore 在干什么本地代理、证书与流量方向2.1 一次 HTTPS 请求经过 FiddlerCore 时发生了什么FiddlerCore 本质是一个本地 HTTP 代理服务器监听在你指定的端口上同时把操作系统或某几个应用的代理设置指向这个端口。当应用发起 HTTPS 请求时它不会直接连接服务器而是先向 FiddlerCore 发一条 CONNECT 请求相当于告诉代理“我要和某个域名建立安全隧道”。接着 FiddlerCore 做中间人解密它用自己的根证书临时生成一张目标域名的站点证书向客户端你的应用伪装成目标服务器同时又以真实客户端的身份去请求上游服务器。这条链路的两个关键点第一任何网络库只要遵循系统代理流量就会被 FiddlerCore 接管不需要改业务代码第二HTTPS 解密要成立客户端必须信任 FiddlerCore 的根证书否则握手会直接失败。这就是为什么你用 FiddlerCore 时会看到多出一个证书安装步骤那不是额外功能而是解密的前置条件。可以这么理解FiddlerCore 在这里不是抓包工具而是一个“中间人服务”宿主把 TLS 终止、证书签发、流量转发全包了。你只需要在 BeforeRequest 事件里拿到完整的请求对象在 BeforeResponse 事件里拿到响应体剩下的就是业务逻辑。2.2 为什么选 FiddlerCore 而不是直接起命令行选择它而不是开一个独立的抓包窗口核心原因有三个。第一它是可编程的。你可以把抓包参数写进配置文件一键启动、自动收集、自动退出完全不需要人工干预这在持续集成环境里非常有用。第二它可以按条件过滤和处理流量。FiddlerCore 允许在回调里依据 URL、域名、HTTP 方法、请求头甚至自定义标记来决定是放行、拦截、修改还是丢弃。这个能力在接口回归时尤其好用你想验证某个响应头在什么条件下会变化完全可以写代码去改响应体然后观察客户端是否产生预期行为。第三它便于和测试框架融合。常见的做法是在测试启动前拉起 FiddlerCore测试结束把它关闭并把抓到的会话导出和基线做对比。纯粹用 GUI 工具很难做到这一步自动化。当然它也不是万能的比如透明代理强制接管没有代理设置的程序就要配合另外的驱动组件才能实现这点后面专门说。2.3 FiddlerCore 的授权与版本边界一个容易忽略但决定成败的问题是授权。FiddlerCore 不是纯免费库它有商业授权限制免费使用通常受限于非商业场景商业分发、打包进收费工具或大规模部署都要购买授权。很多项目在前几周跑得好好的后面准备上线就发现授权问题这是最常见的“翻车”原因之一建议在选型阶段就确认清楚。版本上要留意 API 差异。老版本的 FiddlerCore 一般是和经典 Fiddler 配套的命名空间是 Fiddler核心类叫 FiddlerApplication而较新的版本增加了 FiddlerCore 命名空间API 有调整。网上搜到的示例代码大量是旧版写法直接照抄经常会编译不过。我的习惯是先确认拉到的程序集里有没有 FiddlerApplication 类以此判断是哪种 API再决定参考哪套写法避免浪费一晚上。3. 把 FiddlerCore 集成进你的程序从引用到跑通 HTTPS 解密3.1 最小可运行初始化、绑定端口、关闭先用一个最小 C# 例子把流程跑通。这个例子包含引用程序集、开启代理、注册事件监听和关闭代理是后面所有功能的基础。using System; using Fiddler; class Program { static void Main(string[] args) { // 1. 配置监听端口true 表示同时接管系统代理设置 FiddlerCoreStartupFlags flags FiddlerCoreStartupFlags.Default; FiddlerApplication.Startup(8888, flags); // 2. 注册请求和响应事件 FiddlerApplication.BeforeRequest OnBeforeRequest; FiddlerApplication.BeforeResponse OnBeforeResponse; Console.WriteLine(FiddlerCore 已启动监听端口: 8888按回车退出); Console.ReadLine(); // 3. 退出前注销事件并关闭防止句柄泄漏 FiddlerApplication.BeforeRequest - OnBeforeRequest; FiddlerApplication.BeforeResponse - OnBeforeResponse; FiddlerApplication.Shutdown(); } static void OnBeforeRequest(Session oSession) { Console.WriteLine($请求: {oSession.fullUrl}); } static void OnBeforeResponse(Session oSession) { Console.WriteLine($响应: {oSession.responseCode} {oSession.fullUrl}); } }这里的 Startup 端口参数建议选一个不容易被占用的高位端口比如 8888、8877避免和本地已有的代理工具冲突flags 参数控制启动行为。Default 会修改系统代理设置这意味着程序退出后必须调用 Shutdown 恢复原代理配置这是最常见的坑后面专门展开。事件回调里拿到的 Session 对象是核心数据载体oSession.fullUrl 是完整请求地址oSession.requestBody 和 oSession.responseBody 是字节数组适合做日志落盘或内容改写。注意这里必须在使用后立刻取出数据不能在异步任务里再引用这个对象因为事件结束后 Session 可能被复用。3.2 让本地 HTTPS 流量被解密证书安装与校验如果不处理证书上面这个程序只能抓到 HTTP 明文流量HTTPS 请求只会出现一条 CONNECT 隧道看不到具体内容。FiddlerCore 要解密 HTTPS必须满足两步一是生成本机根证书二是把根证书安装到系统受信任的根证书颁发机构。if (!CertMaker.rootCertExists()) { // 生成并安装根证书到当前用户受信任区 CertMaker.createRootCert(); CertMaker.trustRootCert(); }CertMaker 是 FiddlerCore 自带的证书管理组件。createRootCert 生成根证书trustRootCert 把它安装进系统证书库。生成后最好检查一下是否真的被信任有时杀毒软件或系统策略会拦截信任操作导致明明执行了却没生效。证书这几个参数值得注意根证书有有效期默认生成的证书周期在几年左右过期后所有依赖它的解密都会失败表现为“客户端突然无法访问任何 HTTPS 网站”certmaker 生成的站点证书是动态签发的不需要逐个域名配置这也是它比手工配证书方便的地方。还有一点证书安装只影响当前用户账户。如果你的程序是以服务方式运行的注意服务账户的证书库和当前登录用户不是同一个。常见做法是在安装阶段以管理员身份把证书装到本机计算机账户这样服务进程也能使用但必须评估安全影响根证书一旦泄露或被滥用等于有人可以解密本机所有 HTTPS 流量。生产环境不要随便在机器上装根证书开发机和测试机再这么干。3.3 按域名/进程做过滤与改写响应手头流量一多全量收集既不现实也没必要按条件过滤是第一需求比如只抓某个 API 域的请求。这个诉求用 BeforeRequest 事件里的判断即可实现。static void OnBeforeRequest(Session oSession) { // 过滤只处理目标域名的请求其余直接放行 if (!oSession.Hostname.EndsWith(api.example.local)) { return; } // 过滤请求方法只关注 POST 和 GET if (oSession.HTTPMethod ! POST oSession.HTTPMethod ! GET) { return; } // 改写请求头追加一个调试标识 oSession.oRequest[X-Debug-Tag] fiddlercore-capture; Console.WriteLine($目标请求: {oSession.fullUrl}); }Hostname 属性拿到的是不带端口的域名适合做后缀匹配如果要做精确匹配可以用 oSession.url 取完整路径。改写请求头用 oSession.oRequest 索引器它是多值字典赋值方式不同于普通字典重复赋值会追加多个同名头想要覆盖需要先移除再赋值。响应改写的常用场景是 mock 数据把某个接口的响应体替换为本地 JSON测试前端对异常数据的处理。下面是一个在 BeforeResponse 事件里直接替换响应体的写法。static void OnBeforeResponse(Session oSession) { if (oSession.fullUrl.Contains(/api/user/info)) { // 替换响应体注意同步修改 Content-Length string mockJson {\code\:500,\message\:\mock error\}; oSession.utilSetResponseBody(mockJson); } }utilSetResponseBody 会重新计算 Content-Length 并更新响应头是比较省事的做法。如果手动给 oSession.responseBody 赋值务必自己更新 Content-Length 头否则客户端会一直等不到完整响应体。另外一个细节是响应体的编码utilSetResponseBody 默认按 UTF-8 处理如果原响应是 GBK替换后常见的表现是中文乱码此时需要先转码再赋值。4. FiddlerCore 抓包避坑这 5 个坑我基本每个都踩过4.1 系统代理设置没还原整个系统的网络被“劫持”现象程序崩溃或忘记调用 Shutdown然后浏览器再也打不开网页所有请求都报代理错误检查系统代理设置发现还指向 FiddlerCore 的监听端口。原因FiddlerCore 启动时改动了系统代理正常退出会还原但进程被 kill 掉或未执行 Shutdown代理设置就残留在系统里指向一个已经不存在或不再监听的端口。解决启动时记录原始代理设置退出时强制还原更保险的做法是注册崩溃回调和退出钩子在程序退出的所有路径里都执行还原逻辑。也可以给 Startup 传入不修改系统代理的 flags然后手动指定应用代理但这样无代理感知的程序就抓不到流量通常只在调试独立程序时用。4.2 HTTPS 抓出来的全是 CONNECT看不到任何请求内容现象日志里大量 CONNECT 开头的会话点进去只有隧道信息没有实际请求和响应体业务内容完全消失。原因常见的三个来源根证书没有安装成功安装了但不在受信任的根证书列表里客户端程序不信任当前环境比如某些客户端自带证书固定Certificate Pinning逻辑或使用私有证书库。解决先确认根证书是否真的在受信任列表里trustRootCert 返回 true 不代表系统刷新了缓存有时需要重启目标程序。其次确认目标程序是否走系统代理如果它自己实现了网络栈代理设置对它就无效。证书固定的程序基本无法用这种方式解密这是就没有太多办法的边界必须换环境或让开发加上调试开关。4.3 端口被占用导致启动失败现象Startup 抛异常提示端口已被占用或者启动成功但收到的流量不是本程序的。原因端口被其他代理工具、本地服务或上一次残留的进程占用。解决启动前检测端口可用性写法比较简单用 TcpListener 尝试绑定能绑定就说明端口空闲。另外一个细节如果同一台机器上跑多个基于 FiddlerCore 的工具它们最好用不同的监听端口否则后面启动的那些会接不到流量因为系统代理只指向最后一个写入的端口地址。4.4 回调里做耗时操作整个代理被拖死现象抓包本身没问题但只要并发一高客户端请求全部排队页面等半天才出来或者程序内存一直涨。原因BeforeRequest 和 BeforeResponse 是同步事件在里面做文件写入、数据库访问、同步 HTTP 请求都会阻塞代理线程。特别是在加密流量场景每个请求都要经历解密和再加密耗时翻倍。解决回调里只做轻量数据处理把需要落盘的会话对象转成基本类型URL、时间戳、状态码、字节长度丢进并发队列由后台线程批量消费写文件。注意不要在回调里异步等待队列消费完成你的“异步等”会变成“同步阻塞”。另外一个容易忽视的点是事件不注销导致的泄漏循环创建和销毁代理实例时尤其明显。4.5 某些程序不经过系统代理流量根本不到 FiddlerCore现象浏览器和大部分应用都能抓到但某个命令行工具、游戏客户端或自己写的 Socket 程序完全不出现在捕获列表里。原因不是所有程序都遵循系统代理设置有的程序直接连接远端端口有的读取的是环境变量里的代理配置有的自己写网络层不关心系统代理。解决命令行工具通常可以用环境变量方式绕过这个问题比如设置 HTTP_PROXY 和 HTTPS_PROXY 指向本地监听端口。这类环境变量是对系统代理设置的补充而不是替代可以让那些“不听系统代理”的程序把流量送过来。至于完全自实现网络栈的程序需要依赖透明代理驱动比如用数据包重定向组件把流量强制引导到本地端口这属于另一个技术方向不算 FiddlerCore 本身的功能。5. 进阶把 FiddlerCore 变成你调试管线的“总闸”5.1 把解密后的流量原样转发给第三方分析工具有时本地写完日志还不够希望把解密后的流量交给另一个分析端完整处理。一种常见的落地方案是给 FiddlerCore 配置上游代理将解密后的请求统一转给另一个代理实例做二次分析。FiddlerApplication.SetUpstreamProxy(new Proxy(127.0.0.1, 9090));这样 FiddlerCore 负责解密和粗过滤上游工具负责协议分析和对比各司其职。值得留意的是上游代理也需要能解密 HTTPS否则你看到的是密文等于绕了一圈没解决问题如果只是要记录原始网络交互那就无所谓了。这个思路在做协议栈的迁移验证时很管用。5.2 自动保存会话并做离线对比抓包数据的核心价值在于前后对比。把同一接口在 v1 和 v2 的响应体分别落盘用 diff 工具就能定位异常变更。static void OnBeforeResponse(Session oSession) { // 仅保存配置目录下的目标接口 if (!oSession.fullUrl.Contains(/api/)) return; string fileName DateTime.Now.ToString(yyyyMMdd_HHmmss_fff) _ Guid.NewGuid().ToString(N).Substring(0, 8) .txt; byte[] body oSession.responseBody; File.WriteAllBytes(Path.Combine(captures, fileName), body); }这里有几个细节文件名加了时间戳和随机后缀避免并发写同一文件互相覆盖保存的是字节数组而不是字符串保留原始编码目录先创建好再写否则第一次运行会抛目录不存在异常。要注意的是频繁写文件性能有限单机几个并发没问题压测场景就不建议全量落盘后端批量消费是更好的做法。5.3 小心并发与性能拦截回调里的耗时操作之前提过回调不能阻塞这里补充一个实践经验我用一个全局 Channel 或 ConcurrentQueue 做中转回调里只入队后台起专门线程消费把磁盘写、网络转发这类慢操作全部挪出回调线程。这么做之后代理本身的吞吐量提升了一个量级页面加载卡顿的问题也消失了。别的经验是一开始就加“总开关”按功能开关过滤条件和保存策略否则每次改需求都要重新编译整个工程。我现在的习惯是任何项目接入 FiddlerCore 都先跑通最小骨架再做业务因为很多配置项是一环扣一环的端口不通就排查占用证书失效就看信任列表流量没进来就检查代理设置和过滤条件。保持记录每次改动前后的网络状态对比排查速度会快不少。希望这篇笔记能帮你在 FiddlerCore 抓包这条路上少走几个弯路。本文还有配套的精品资源点击获取