
简介这是一份基于FiddlerCore封装的开源抓包工具源码适合需要HTTP/HTTPS会话捕获与调试的.NET开发人员。资源以zip形式发布共33个文件核心为11个C#源码文件、4个DLL运行库及4个EXE示例程序并附带必要的配置文件、文本说明和调试符号。代码支持两种抓包方式通过系统代理进入以及通过自定义WebProxy启动独立代理端口并包含证书管理和自动化操作辅助类参考了社区常见FiddlerCore示例加以整合。压缩包整体仅717KB结构清晰便于学习和二次修改。已有1577人学习下载适合正在寻找免费FiddlerCore抓包方案、想快速集成代理抓包功能或理解证书处理流程的开发者参考。1. FiddlerCore抓包抓包引擎不一定要开着图形界面大多数人提到 FiddlerCore第一反应是“那个能抓包的工具”再仔细看一眼就又绕回去开图形界面了。我在做接口自动化测试平台时遇到一个很实际的问题CI 环境里跑用例请求出错时想留一份当时的完整流量图形界面里那条请求早就被新流量冲走了靠人盯根本盯不住。FiddlerCore 解决的就是这个问题——它把抓包引擎本身打包成一个可引用的 SDK让你在自己的进程里直接起一个代理内核流量进来、出去、改什么、放行还是丢弃全由代码决定不依赖那个黑匣子一样的 GUI。这篇文章写给正在搭流量录制回放、接口自动化、本地调试工具的人目标是让你看完就能把 FiddlerCore 接入到自己的项目里。2. FiddlerCore是一个SDK不是Fiddler的另一个壳2.1 事件驱动的代理内核FiddlerCore到底怎么工作理解 FiddlerCore先要把“抓包”拆成两个动作一是把网络流量引导过来二是对流量的内容做处理。FiddlerCore 做的事是在你的程序里起一个 HTTP 代理端点然后通过把系统代理指到这个端点让本机或同局域网设备的 HTTP/HTTPS 流量都从它这里经过。它不做界面而是把每个经过的请求和响应包装成一个 Session 对象然后触发你挂上的事件回调。为什么采用事件而不是阻塞队列因为抓包场景里很多操作是“要赶在流量真正发出去之前做完”的比如往请求头里注入一串测试标识、把某个线上接口的响应替换成本地 Mock 数据。如果用一个队列把流量先收起来再让业务代码轮询就很难做到“改完再放行”这种实时性。事件回调模型让业务代码在请求发出前、响应返回前、完整会话结束时各有一个介入点这也是 FiddlerCore 和单纯用 Socket 写代理之间最根本的差别。2.2 最小可用接入三行初始化和一个回调先看一段能跑起来的最小代码这是 FiddlerCore 最常见的接入骨架using Fiddler; var settings new FiddlerCoreStartupSettingsBuilder() .ListenOnPort(8888) // 代理监听端口 .RegisterAsSystemProxy(true) // 注册为系统代理接管本机流量 .DecryptHTTPS(true) // 解密 HTTPS先决条件是安装根证书 .OptimizeThreads(true) // 让 FiddlerCore 根据 CPU 核数调线程池 .Build(); FiddlerApplication.BeforeRequest OnBeforeRequest; // 请求发出前 FiddlerApplication.BeforeResponse OnBeforeResponse; // 响应返回前 FiddlerApplication.AfterSessionComplete OnAfterSessionComplete; // 会话结束 FiddlerApplication.Start(settings); // 程序退出前 FiddlerApplication.Shutdown();这段代码里有几个参数直接影响抓包结果。ListenOnPort 是代理服务监听的端口手机抓包时后续要让手机把代理指向这个端口所以端口要选一个不被占用的固定值我一般用 8888如果用 8888 被别的服务占了就改用 8899。RegisterAsSystemProxy(true) 的含义是自动修改操作系统的代理设置让本机所有走 HTTP/HTTPS 的流量都进入 FiddlerCore这一步如果为 false就只能手动去给单个客户端配代理。OptimizeThreads(true) 在多并发请求的场景下很有用FiddlerCore 线程模型默认偏保守改成 true 之后高并发会话的处理能力明显好一些。回调方法里的参数都是 Session 对象它是理解和操作流量的入口。BeforeRequest 表示请求还没发出去这时可以改头部、改请求体甚至直接构造一个假响应返回BeforeResponse 表示响应已经从目标服务器拿到但还没回到客户端适合修改响应体或做重试逻辑AfterSessionComplete 表示整个会话已经走完适合做流量留痕和统计。2.3 会话对象与请求响应的数据入口Session 对象是 FiddlerCore 里最关键的类几乎所有有用的信息都从它里面取。我常用的数据入口就三类请求信息、响应信息、会话标记。private void OnAfterSessionComplete(Session oSession) { // 请求侧 var url oSession.fullUrl; // 完整URL含query string var reqHeaders oSession.oRequest.headers; // 请求头集合 var reqBody oSession.RequestBody; // 请求体字节数组 // 响应侧 var respStatus oSession.responseCode; // HTTP状态码 var respBodyBytes oSession.ResponseBody; // 响应体字节 // 自定义标记写在请求头上的调试信息 var token oSession[X-Debug-Token]; }注意 oHeaders 和 oRequest.headers 的区别前者是请求头对象后者才是真正从线上拿到的原始请求头修改时要基于 oSession.oRequest 去改。RequestBody 和 ResponseBody 在 FiddlerCore 里默认返回字节数组用 Encoding.UTF8.GetString() 转字符串做解析即可不要直接调 ToString()拿到的类型名而不是内容。这里还要提一个容易理解错的地方BeforeRequest 里读取请求体时如果内容较大FiddlerCore 可能还没有把整个请求体读取完。这时要读 Body建议先调用 oSession.utilLoadRequest()它会把请求体完整加载进内存并返回字节数组。同样BeforeResponse 里读响应体先调用 oSession.utilLoadResponse() 再取 ResponseBody能避开不少“读出来是空串”的问题。3. 抓包前的三个必调开关端口、系统代理与HTTPS证书3.1 端口与系统代理的关系以及端口被占的排查端口和系统代理看似是两个独立配置实际是一条链路上两个必须同时满足的条件。代理端口起不来后面什么都没得抓端口起来了但系统代理没配上只有手动把客户端流量指过来才有效。我的经验是按端口、系统代理、证书三个顺序做基础配置排查。端口被占用是最常见的翻车点。FiddlerCore 的 Start 方法在端口被占时会直接抛异常但有些情况下异常信息比较隐晦我建议在启动 FiddlerCore 之前主动做一次端口探测using System.Net; using System.Net.Sockets; public static bool IsPortAvailable(int port) { try { var listener new TcpListener(IPAddress.Loopback, port); listener.Start(); listener.Stop(); return true; } catch (SocketException) { return false; } } // 启动代理前 if (!IsPortAvailable(8888)) { throw new InvalidOperationException(端口8888被占用请换端口或释放占用进程); }这段代码的关键不是检测本身而是把“选端口”变成一个确定性动作。写死端口第一次可能没事跑久了容易和别的开发工具冲突尤其有些本地服务会随机扫端口我后来干脆做一个端口分配表把 8888-8899 划成 FiddlerCore 专用段启动时顺序找一个可用端口。RegisterAsSystemProxy(true) 这个开关也要单独说。它改的是 Windows 系统代理设置程序退出时 FiddlerCore 的 Shutdown 方法会尝试恢复原系统代理但如果进程是被强杀的系统代理可能停留在指向 8888 端口的状态。这时你会发现浏览器突然上不了网因为代理指向的端口已经没人监听了。碰到这种情况去系统设置里把代理关闭或者手动恢复原代理地址即可这是 FiddlerCore 接入原生应用中一个非常经典的现场问题。3.2 HTTPS解密三件套的设置顺序证书、DecryptHTTPS、回调HTTPS 解密是 FiddlerCore 使用中被误解最多的部分。不少人以为设置了 DecryptHTTPS(true) 就能抓 HTTPS结果打开抓包一看全是 CONNECT 隧道看不到任何明文内容。原因很简单FiddlerCore 要做中间人解密客户端必须信任 FiddlerCore 持有的根证书否则 TLS 握手在客户端就失败了要么连接直接断掉要么客户端报证书错误。根证书的生成和安装一般在 Start 之前完成// 1. 先确保根证书存在 if (!FiddlerApplication.CertificateMaker.CheckForExistingRootCertificate()) { FiddlerApplication.CertificateMaker.CreateRootCertificate(); } // 2. 安装到当前用户信任区 FiddlerApplication.CertificateMaker.InstallCertificate(); // 3. 再启动代理并开启解密 FiddlerApplication.Start(settings);这个顺序不能乱。CertificateMaker 是 FiddlerCore 提供的一个证书操作入口CreateRootCertificate 会在本机生成一个根证书生成之后系统并不知道这张证书是可信的必须 InstallCertificate() 把它装进受信任的根证书颁发机构。如果跳过安装直接 Start客户端发起的 TLS 握手会因为“证书不受信任”而失败表现就是抓不到 HTTPS 请求或者客户端直接报错。还有一个小坑InstallCertificate 需要在程序有权限的环境下执行如果用普通权限跑安装证书会失败或只装到当前用户下。Linux 服务器上跑 FiddlerCore 时证书要装到 /etc/ssl/certs 这种系统级信任区和 Windows 的行为不一样做跨平台部署时要先确认目标环境的证书信任机制。3.3 只抓不解密透明代理与DoNotDecrypt的使用边界不是所有场景都需要解密 HTTPS。如果你只是想统计请求量、记录 URL、看状态码分布解密反而会带来额外的 CPU 开销和证书风险。FiddlerCore 里有透明的转发模式让流量原样穿过不解密、不改写这种方式在抓包服务里相当于只做一个“流量镜像口”。var settings new FiddlerCoreStartupSettingsBuilder() .ListenOnPort(8888) .RegisterAsSystemProxy(true) .DecryptHTTPS(false) // 抓包但不解密 .Build();DecryptHTTPS(false) 时HTTPS 请求的 URL 和域名还能看到但请求体响应体全是密文。这个模式适合做流量采样统计因为不用安装证书接入成本低也不会有证书信任问题。而一旦业务需要修改请求或响应的内容必须把解密打开同时接受“证书安装 客户端信任”这两个前置条件。还有个容易被忽略的选项叫 DoNotMakeChanges。开启后 FiddlerCore 会减少对会话内容的改动比如不会主动给请求加头这在某些后端对请求头敏感的场景下很关键。默认情况下 FiddlerCore 可能会在某些版本里加入自己的代理痕迹头如果你的目标是做一个尽可能“不被发现”的抓包旁路把 DoNotMakeChanges 设为 true 能减少一层干扰。4. 移动App与小程序抓包把FiddlerCore变成手机代理4.1 手机代理指向PC最小配置把 FiddlerCore 用在手机 App 抓包本质是让手机上的流量经过同一台 PC 上的代理端口。电脑上 FiddlerCore 监听 8888手机连同一个局域网代理设置里把主机指向电脑 IP、端口设为 8888HTTP 流量就会自动被 FiddlerCore 接管。但 HTTPS 解密在手机上有一个额外环节手机必须信任 FiddlerCore 生成的根证书。证书不能只装在电脑上要导出后传到手机安装。Android 和 iOS 的安装路径不同Android 上是把证书导入到“CA 证书”或“用户凭据”iOS 上是安装到描述文件然后在设置里打开证书信任开关。这个环节最容易遇到的问题就是手机上安装证书以后依然抓不到 HTTPS 明文这时要检查证书是否完整安装、日期是否正确、以及手机代理是否真的走通了。手机抓包还有一个时间点要注意代理设置后已经建立的连接不会立刻切换到新代理。微信、支付宝这类长连接 App往往是打开时建立连接后面一直复用所以设置完代理后要么切换 App 页面触发新请求要么彻底杀掉 App 进程再重开。否则你看着代理配置没问题就是等不到流量。4.2 微信小程序与内嵌WebView的特殊抓包姿势小程序抓包这两年问得很多一个现实情况是小程序的流量从微信进程发出去而不是从小程序独立进程发出去。所以抓包工具能不能抓到小程序的包既取决于代理是否生效也取决于微信自身是否信任你安装的证书。微信在这方面限制比较严。iOS 上的微信对于 HTTPS 请求很多版本会内置证书校验逻辑即使你在系统层面安装了 FiddlerCore 的根证书TLS 握手依然可能失败。Android 上相对宽松但 Android 7 以后默认不再信任用户安装的 CA 证书只有系统证书才被信任所以手机抓包经常出现“安装了证书依然解密失败”的玄学问题。常见做法是把用户证书移动到系统证书目录这需要手机已经 root 或者能解锁 bootloader。另外一个更隐蔽的坑是 WebView 代理行为。App 里内嵌的 WebView 有些不走系统代理设置而是使用 App 代码里单独配置的网络库策略。这种情况下即使你给手机设置了代理小程序的页面和 WebView 的请求也可能完全不进来。排查时可以先确认一个普通的浏览器请求是否被抓到如果浏览器能抓到而 App 抓不到说明问题出在 App 的网络栈对代理的适配而不是代理配置本身。4.3 遇到App的证书校验怎么办调试允许和边界业务 App 为了防止中间人攻击会在代码里做证书绑定Certificate Pinning即使系统信任了你的根证书App 依然不认账表现是连接失败或者直接报错。对于开发者自己维护的测试 App团队内部常见的做法是给测试包做一个开关校验失败时放行对于第三方 App社区里也有不少辅助调试插件可以在测试机上临时绕过校验。这里必须说一个边界这些手段只允许用于你有权调试的设备比如自己公司的测试机、自己开发的 App。对没有授权的流量做中间人解密不仅技术上困难法律上也有明确的合规红线。我在这类问题上只做一件事先用普通浏览器的流量验证 FiddlerCore 解密链路是通的再判断问题出在证书链路还是 App 的主动校验上。如果链条本身不通先修系统设置不要急着上绕过方案。5. FiddlerCore抓包常见问题与避坑记录5.1 坑一什么都抓不到先查系统代理和端口现象FiddlerCore 启动了控制台不报错但请求日志里一条流量都没有。原因大概率是系统代理没有真正生效或者网络流量本来就请求了别的代理。还有一种情况是代理启动时端口被某个未知进程抢占了但异常被吞掉。解决先确认监听端口正常用 netstat -ano | findstr 8888 看端口是否处于 LISTEN。再查系统代理Windows 设置里看代理指向的地址和端口是否一致。最后用浏览器访问一个普通 HTTP 网站如果浏览器能抓到流量就排除代理链路问题再去查 App 自身是否用了自定义网络栈。5.2 坑二只有CONNECT隧道没有解密后的内容现象抓包记录里大量 CONNECT 开头的会话没有真正的请求头和响应体。原因CONNECT 是 HTTPS 代理握手中的第一步说明客户端和代理之间连接成功了但后续的 TLS 握手没有成功或者 DecryptHTTPS 配置是 false。解决先把 DecryptHTTPS 确认为 true再检查根证书是否已安装且被客户端信任。手机场景下要额外确认证书装进了系统信任区。如果证书没问题还出现 CONNECT抓一下 TLS 握手失败的具体报文通常是证书颁发者不被信任导致的。5.3 坑三改请求体后Content-Length没重算现象在 BeforeRequest 回调里改了请求体内容结果请求发出去后服务端报 400 或请求参数读不出来。原因改了请求体字节数但没有同步修改 Content-Length 请求头后端按旧长度截取或拼接请求体导致数据错位。解决每次修改完请求体强制重写 Content-Lengthprivate void OnBeforeRequest(Session oSession) { var newBody { \debug\: 1 }; oSession.RequestBody Encoding.UTF8.GetBytes(newBody); oSession.oRequest.headers[Content-Length] oSession.RequestBody.Length.ToString(); }这里有个细节一旦给 RequestBody 赋值FiddlerCore 内部的请求体状态会更新但 Header 不会自动跟着变必须手动同步 Content-Length。同理修改响应体后也要处理响应头的 Content-Length。5.4 坑四长时间驻留后内存与句柄持续增长现象FiddlerCore 作为服务跑几天后内存占用翻倍甚至出现句柄耗尽导致代理假死。原因很多会话对象在回调执行完后没有被释放或者某些响应流没有被读取完全导致连接资源无法回收。FiddlerCore 在高并发下如果不对 Session 对象做留存管理内存增长几乎必然发生。解决两个策略并行。一是回调里做到“用完即走”需要留存的字段提取到业务实体里不要保存整个 Session 对象。二是限制请求体响应体的自动加载绝大多数分析场景只需要头和部分 Bodyprivate void OnAfterSessionComplete(Session oSession) { var respBody string.Empty; if (oSession.ResponseBody.Length 10 * 1024) // 只保留小于10KB的Body { respBody Encoding.UTF8.GetString(oSession.ResponseBody); } // 存到自己的存储里然后让 oSession 走人 }关键的认知是 Session 对象本身不小里面持有着完整的请求头、响应头、Body 字节数组。不要图方便直接放到 List 里做批量分析那是把内存往悬崖上推。5.5 坑五回调里读响应Body拿到的是空串现象BeforeResponse 里想提取响应里的某个字段读 ResponseBody 结果是空。原因FiddlerCore 在 BeforeResponse 触发时响应体并未保证完整读入内存。它是一个流式代理Body 可能在事件触发时只读取了一部分。解决先调用 utilLoadResponse 确保完整加载private void OnBeforeResponse(Session oSession) { oSession.utilLoadResponse(); // 强制读取完整响应体 var body Encoding.UTF8.GetString(oSession.ResponseBody); Debug.WriteLine(body); }这一条在写响应拦截和 Mock 逻辑时几乎是必踩的坑。判断“要不要加 utilLoadResponse”有个简单标准只要你在事件里访问 ResponseBody 且目标是拿内容做逻辑判断就加如果你只是想拿 responseCode 做统计不需要加。5.6 坑六证书过期、卸载不干净导致二次启动报错现象程序升级重启后 FiddlerCore 启动失败提示证书相关错误或者新生成证书与旧证书不一致导致客户端校验失败。原因FiddlerCore 默认证书有有效期过期后不会自动重新生成。旧版本生成的根证书没有清理新版本检测到旧证书存在不重新创建但旧的私钥可能已经丢失或路径变化。解决启动前做一次证书状态检查和重建if (!FiddlerApplication.CertificateMaker.CheckForExistingRootCertificate()) { FiddlerApplication.CertificateMaker.CreateRootCertificate(); } else { // 证书已存在但不一定有效按需判断是否重建 FiddlerApplication.CertificateMaker.RemoveCertificate(); FiddlerApplication.CertificateMaker.CreateRootCertificate(); }我一般会在正式环境里把这个逻辑放到“证书目录可写”的前提下并且每次启动时打印证书指纹这样后续排查证书问题时能快速判断当前进程用的是哪张证书。证书相关的错误信息往往藏在异常堆栈最深处拿到后先看是不是“certificate has expired”或“private key not found”基本能定位是这类问题。6. 进阶把FiddlerCore从记录器改成拦截器再盯到WebSocketFiddlerCore 的记录能力很多人用过但把它改造成一个带逻辑的拦截器价值会高一个量级。最常见的做法是在 BeforeRequest 里按 URL 规则做请求改写或直接短路private void OnBeforeRequest(Session oSession) { if (oSession.fullUrl.Contains(/api/pay/)) { oSession.utilCreateResponseAndLoadBody({\code\:500,\msg\:\mock失败结果\}); oSession.responseCode 200; oSession.oRequest.headers[Host] mock.local; // 标记来源 oSession.state SessionStates.Done; // 不再转发到服务器 } }这样就能在测试环境里把某个真实接口的响应替换成预设数据比改数据库做测试数据快得多。拦截器的核心思路是确认逻辑判断、构造响应、终止转发。三个动作缺一不可尤其是最后把 oSession.state 改为 Done否则请求还是会继续发到线上。WebSocket 和 wss 流量是个容易忽视的增量点。FiddlerCore 对 WebSocket 支持不如 HTTP 那样透明它的处理方式是在 BeforeRequest 阶段识别 Upgrade 头然后透传后续帧。要做 WebSocket 消息级别的抓取需要在 AfterSessionComplete 之后从会话里检查是否有 WebSocket 帧数据再做解析。这个方法不够优雅但能解决“wss 流量完全看不见”的问题。如果业务里 WebSocket 是核心路径更稳的做法是让客户端把消息主动上报一份到调试接口不要把 FiddlerCore 当作 WebSocket 协议的完整调试器它在纯 WebSocket 场景下边界暴露得很快。我自己的习惯是 FiddlerCore 只承担 HTTP/HTTPS 链路的录制、改写和状态统计这三件事WebSocket 的细粒度调试交给业务侧日志埋点。最初做流量分析平台时我把所有希望都压在 FiddlerCore 上结果项目上线后被 WebSocket 和长连接的盲区拖了两周。后来把边界划清楚每个工具只解决一段问题FiddlerCore 负责 HTTP 请求响应的录制和回放平台负责展示复杂度一下就降下来了。希望这篇关于 FiddlerCore 抓包的拆解能帮你在接入前避开那些我踩过的坑让你在调试工具上节省的时间真正花在业务本身。本文还有配套的精品资源点击获取