
1. 先说清楚HTTPS到底在防谁、防什么很多人一开始接触HTTPS只知道“加了S更安全”但“更安全”到底体现在哪HTTP时代又暴露了什么问题其实没太想明白。不说清楚这个背景后面讲Fiddler怎么实现内容劫持你就很难理解它到底动了什么手脚。1.1 HTTP时代的裸奔惨状HTTP协议在设计时根本没考虑加密数据在网络上传输就是纯文本。举个特别直观的例子你在咖啡厅连了一个公共Wi-Fi打开一个HTTP网站输入账号密码点击登录——这一串操作里你的账号、密码、Cookie、聊天内容全都以明文形式在网络链路中传递。这是什么概念呢相当于你写了一张明信片寄出去邮递员、分拣员、转发站的工作人员只要想看你写的内容随手就可以翻。HTTP时代的网站流量对链路中任何能截获数据包的人来说完全是透明的。更麻烦的是HTTP不仅泄漏内容它连“篡改”都防不住。攻击者可以在数据包经过的路由器上做手脚把你收到的网页改成带恶意代码的版本也可能在你访问某下载站时把安装包替换成捆绑木马的版本。这种攻击叫“中间人攻击”网络里的任何一个介入节点都可能变成那个“中间人”。我最早对这件事有直观感受是很多年前用抓包工具看公司内部某个老系统的登录请求username和password就明晃晃躺在请求体里连编码都没做。那时候才真正明白为什么银行、电商、社交平台都分秒必争地全面上HTTPS——明文的HTTP在网络世界里基本等于裸奔。1.2 HTTPS到底解决了哪三个问题HTTPS全称是Hyper Text Transfer Protocol over Secure Socket Layer本质上就是“跑在加密通道上的HTTP”。它并不是一个全新的应用层协议而是给HTTP包了一层安全外壳重点解决三个问题第一机密性。数据在传输过程中经过加密即使被截获没有密钥也读不出内容。这个解决的是“偷看”的问题。第二完整性。接收方能够校验数据在传输过程中有没有被篡改一旦被改过就能发现并拒绝。这个解决的是“换包”的问题。第三身份认证。客户端能够确认自己正在通信的服务器确实是目标服务器而不是伪装的钓鱼站点。这个解决的是“冒充”的问题。这三个问题分别对应加密算法、消息认证码/数字签名、数字证书技术。理解HTTPS的钥匙就是理解这三块东西怎么组合在一起发挥作用。而我后来在做抓包、做接口调试、做性能测试时反复遇到的情况是很多人证书装上了抓不到包或者浏览器直接报警告根源都在于没吃透上面这三个问题——尤其是“身份认证”和“证书”这两块几乎是一切的枢纽也是Fiddler能“劫持”HTTPS的关键入口。2. HTTPS的加密内功一次完整的TLS握手拆解2.1 对称加密的快与非对称加密的稳HTTPS背后的加密体系核心是两类算法配合使用对称加密和非对称加密。对称加密就是加密和解密用同一把密钥。比如你用密钥K加密一段文字对方用同一把K解密。常见的有AES、ChaCha20等。对称加密最大的优点是快适合加密大量数据。但它有一个致命难题密钥怎么安全地送到对方手里如果在网络上直接传密钥那密钥本身又有可能被截获加密就等于白做了。非对称加密则是一对密钥公钥和私钥。公钥可以公开分发私钥只有自己保存。用公钥加密的数据只有对应的私钥能解开反过来用私钥签名的数据所有人都能用公钥验证确实是本人发的。常见的有RSA、ECDSA等。非对称加密解决了密钥分发问题但缺点是慢加密大量数据时性能扛不住。所以TLS协议取了个巧用“混合加密”的方案握手阶段用非对称加密协商出一个临时对称密钥叫会话密钥后续所有HTTP数据都用这把会话密钥走对称加密。这样既解决了密钥分发难题又保证了大数据量的加解密速度。我经常用一句大白话跟朋友解释非对称加密负责“安全地送钥匙”对称加密负责“高效地开关门”。2.2 数字证书凭什么相信这把公钥是真的这里有一个必须较真的问题就算服务器把公钥发给客户端客户端怎么知道这把公钥确实是目标服务器的而不是攻击者中途换掉的如果没法确认整个加密体系就建立在一个沙堆上——攻击者完全可以自己伪造一对公钥私钥把自己的公钥发给客户端然后冒充服务器。这个场景在学术上叫“中间人攻击的密钥交换阶段”是目前所有SSL剥离、代理劫持攻击的入口。解决这个问题的核心机制就是数字证书以及它背后的CA体系。服务器运营方会向证书颁发机构CACertificate Authority申请一张证书证书里包含服务器的域名、公钥、有效期、颁发者等信息最关键的是CA会用自己私钥对这份证书做数字签名。客户端在收到证书时会用系统内置信任的CA公钥去验证签名如果验证通过说明这张证书确实是由可信CA签发的、中间的域名和公钥都没有被篡改过那就可以信任证书里的公钥。打个比方你要确认一个陌生人真的叫张三并住某地址不能光听他自己说得看他的身份证。身份证由公安局签发而公安局的章就是权威背书。客户端内置信任的CA列表就相当于“公安局”的名单。浏览器、操作系统在安装时都会内置一批全球公认的CA根证书信任链就是从根证书开始的。2.3 一次TLS握手走一遍全流程把上面的元素串起来一次完整的TLS握手大概是这么走的以最常见的TLS 1.2为例客户端发起ClientHello带上支持的加密套件列表和一个随机数。服务器回应ServerHello选定加密套件带上自己的数字证书和另一个随机数。客户端验证证书合法性确认服务器身份可信后生成一个新的随机数即预主密钥用服务器公钥加密后发给服务器。服务器用自己的私钥解密得到预主密钥。现在双方都拥有了三个随机数可以用约定的算法推导出同样的会话密钥。之后双方互相发送“Finished”消息验证握手是否成功确认无误后开始用对称加密传递HTTP数据。这个流程里有一个细节值得关注前两个随机数是明文传递的第三个随机数才是核心机密它被公钥加密保护。攻击者即使截获了前两个随机数没有第三个随机数也推不出会话密钥。这种“三个随机数混合推导”的设计是TLS协议的历史演进结果主要为了增加随机性和安全性。理解了这套握手流程再去理解Fiddler“劫持”HTTPS的原理就只隔着一层窗户纸了——它要做的就是让客户端和服务器都以为自己在和真正的对方通信但实际上两者的“中间人”是Fiddler自己。3. Fiddler凭什么能“劫持”HTTPS中间人原理全解析3.1 Fiddler的基本身份代理服务器Fiddler本质上是一个HTTP代理。它启动后会监听本机的一个端口默认8888并且会自动修改系统代理设置让所有HTTP/HTTPS请求先经过它。也就是说浏览器的请求不再直接发往服务器而是先发给Fiddler由Fiddler转发给服务器回来的响应也先经过Fiddler再交给浏览器。看到这你会发现Fiddler天然就处在客户端和服务器之间它已经站在“中间人”这个位置上了。但如果只是转发它只能看到加密后的密文没有任何意义。真正让它能“解开”密文看明文的是证书体系里一个特殊的操作——信任自定义根证书。3.2 一切的关键安装Fiddler根证书Fiddler在首次使用时会生成一对自己的根证书叫“Fiddler Root Certificate”。当你勾选“Trust Root Certificate”或者手动安装这个证书并把它加入系统信任列表后就相当于告诉操作系统和浏览器以后Fiddler签发的证书都算可信的。这一步一旦完成Fiddler的“劫持”之路就打通了。之后你对任意HTTPS站点发起请求流程会变成这样客户端的请求先到达FiddlerFiddler收到客户端发来的ClientHello后不回真正的服务器证书而是动态生成一张以目标域名为CN的“伪造证书”用Fiddler自己的根证书私钥来签名然后把这张伪造证书发给客户端。客户端校验证书时发现它是由已受信任的Fiddler根证书签发的于是通过验证认为“这是可信的服务器”接着完成与Fiddler之间的TLS握手。与此同时Fiddler又作为客户端与真正的服务器建立另一条TLS连接用真正的证书完成握手和验证。之后就是两条平行的加密通道浏览器与Fiddler之间一条Fiddler与真实服务器之间一条。浏览器发给服务器的数据先用浏览器与Fiddler约定的密钥加密Fiddler收到后解密看到明文再重新用另一把密钥加密后转发给服务器。反过来也一样。这就是经典的中间人攻击MITM流程。Fiddler不是破解了HTTPS而是利用了“客户端信任了可自定义根证书”这个前提重新建立了两段独立的加密通道。严格来说HTTPS协议本身并没有被攻破真正被攻破的是客户端对“根证书信任列表”的防线。这也是为什么你在给手机装Fiddler证书时系统会弹出一堆风险警告——它确实是一个极度敏感的操作。3.3 两条连接各自的密钥为什么能还原出明文很多人会问Fiddler解密后它怎么知道怎么解答案很简单因为每段TLS连接的主密钥Master SecretFiddler自己都持有。在客户端与Fiddler这一段协商密钥时的私钥或预主密钥信息掌握在Fiddler手里在Fiddler与服务器这一段同样如此。TLS握手中涉及密钥推导的信息对Fiddler来说全部可见。所以只要Fiddler愿意它能拿到两端会话的明文。我们常见的抓包工具Wireshark如果想要解密TLS流量也需要单独配置SSLKEYLOGFILE把浏览器的密钥日志导出再喂给Wireshark。而Fiddler的方案更彻底它直接把自己变成了TLS连接的端点密钥自然全都经过它。这个设计上的差异决定了Fiddler在“调试应用层HTTP请求”这个场景里极好用但在“透明分析底层流量”这个场景里不如Wireshark全面。我个人的理解是Fiddler这套机制本质上是把HTTPS的“端到端加密”降级成了“两段式加密”中间一段明文留给了本地调试工具。这在你自己掌控设备、明确知情的情况下是完全合法的调试手段但如果用在未经他人同意的场景里那就是不折不扣的攻击行为。做安全测试时一定要在授权范围内操作这个底线不能碰。4. 实操用Fiddler解密HTTPS并抓包的完整流程4.1 下载安装与基础设置Fiddler有两个常见版本Fiddler Classic经典免费版和Fiddler Everywhere跨平台付费/试用版。我日常用得最多的是Fiddler Classic它免费、轻量、Windows平台下足够稳定对大多数开发和测试场景完全够用。下载安装就不多说了官网下载默认下一步即可。装完后打开可以看到主界面左边是会话列表右边是Inspectors等详情面板。开启HTTPS解密只差几步打开菜单Tools - Options - HTTPS勾选“Capture HTTPS CONNECTs”和“Decrypt HTTPS traffic”。第一个选项让Fiddler能够拦截HTTPS连接请求CONNECT方法第二个选项决定是否对拦截到的流量进行解密。勾选后Fiddler会提示你安装根证书点“Trust Root Certificate”按提示确认证书会安装到Windows的“受信任的根证书颁发机构”存储区。这里有一个很关键的操作顺序先开启解密再安装证书。如果你先把证书装了再开解密有时候Fiddler不一定能把证书正确加入解密白名单导致后面抓不到包。我踩过这个坑后来固定的流程是先开开关再装证书再重启Fiddler一气呵成。Fiddler Classic默认只监听本机回环地址的流量。如果想抓其他设备的流量需要在Connections选项卡里勾选“Allow remote computers to connect”。如果要抓本机浏览器的HTTPS其实默认配置就够了。4.2 证书安装的“信任”范围细节安装证书时很多新手会忽略证书存储位置的选择。给Windows系统安装Fiddler证书时一定要把证书放入“受信任的根证书颁发机构”而不是“个人”或“中间证书颁发机构”。否则即便你安装了浏览器依然会报警告。安装完成后可以在浏览器地址栏访问任意HTTPS网站然后点击地址栏左侧的小锁图标查看证书信息。如果看到证书颁发者是“DO_NOT_TRUST_FiddlerRoot”说明解密已生效。这是我判断配置是否成功最直接的方法比看任何教程都靠谱。4.3 手机抓包Android与iOS的配置差异手机抓包是Fiddler的常见需求场景但也最容易出问题。先讲通用步骤先将手机和电脑连到同一个局域网电脑查看本机IP命令行输入ipconfig找无线网卡的IPv4地址。在Fiddler的Connections里勾选“Allow remote computers to connect”保持端口8888不变确认后重启Fiddler。手机上设置Wi-Fi代理手动代理服务器填电脑IP端口填8888。用手机浏览器访问 http://电脑IP:8888 会看到一个Fiddler Echo Service页面点击页面里的“FiddlerRoot certificate”链接下载证书然后安装并信任。到这里iOS和Android就分道扬镳了。iOS相对简单安装证书后还需要去“设置 - 通用 - 关于本机 - 证书信任设置”里把Fiddler证书的完全信任开关打开。很多人在iOS上装完证书还是抓不到包绝大多数原因就是漏了这一步——iOS默认不信任用户手动安装的证书必须手动开启完全信任。Android的情况就要复杂很多。Android 7.0以上的系统应用默认只信任系统证书不信任用户安装的证书。也就是说就算你在设置里装好了Fiddler证书普通App的HTTPS请求依然不会走Fiddler解密Fiddler只能看到一堆TCP CONNECT记录而看不到里面的明文HTTP内容。我们常用的处理方式有这么几种一是用Android 6.0或更老版本的手机或模拟器这些版本应用默认信任用户证书抓包省心二是Root手机后把用户证书移到系统证书目录三是如果只是调试自己开发的应用在应用代码里配置NetworkSecurityConfig允许信任用户证书。对大多数普通测试场景我建议直接用Android 6.0模拟器成本最低、复现最稳定。4.4 从抓到包到看懂包Inspectors面板怎么用解密成功后在Fiddler主界面点击任意一条HTTPS会话下方Inspectors面板就能直接显示明文内容。WebForms选项卡可以结构化展示POST表单参数Headers选项卡展示完整的请求/响应头Raw选项卡展示原始的HTTP报文。我最常用的是Raw因为它展示的是最真实的数据组织方式排查一些格式问题时更直观。如果需要修改请求内容做测试还可以在Inspectors里右键选择“Unlock for Editing”改完点“Replay”重放请求。这在调试接口签名、模拟不同参数场景时非常好用。比如我想验证后端对某个字段的边界校验直接改参数重放几秒钟就能得到结果比改代码重新编译高效太多。4.5 弱网模拟Fiddler的一个隐藏实用功能测试环境里经常要模拟弱网场景——限速、丢包、高延迟来验证客户端在这些情况下的表现。Fiddler自带了一个简单限速功能位置在Rules - Performances - Simulate Modem Speeds勾上之后Fiddler会自动对流量做延迟限制模拟窄带网络。不过这个内置模拟精度一般只能模拟一个固定速度。要想更精细地控制上下行带宽和延迟可以在FiddlerScript里自定义OnBeforeRequest和OnBeforeResponse通过Thread.Sleep配合随机函数实现波动延迟。我曾经用这个方案模拟了三种网络环境高速Wi-Fi、弱信号4G、地铁高峰期网络。实现方式不复杂就是在脚本里根据请求URL或Host匹配不同的延迟策略实测效果还挺贴近真实场景。FiddlerScript的完整语法可以查官方文档这里先给一个最小示例片段点到为止static function OnBeforeRequest(oSession: Session) { if (oSession.HostnameIs(api.example.com)) { System.Threading.Thread.Sleep(500); } }这类脚本化的控制才是Fiddler真正强大的地方也是它和一般抓包工具拉开差距的重要原因。配置一次之后测试效率提升非常明显。5. 常见问题与排查技巧实录5.1 证书装了浏览器还是报不安全警告这是最常遇到的问题。出现这类情况先按顺序排查三件事第一确认勾选了“Decrypt HTTPS traffic”没勾选的话Fiddler根本不会对HTTPS连接做拦截浏览器自然收到的是真正的服务器证书不会有问题第二确认证书安装到了“受信任的根证书颁发机构”如果装到个人存储区浏览器并不认可第三确认Fiddler和浏览器都重启过证书信任关系在部分浏览器中需要重启才生效。还有一个容易忽略的点如果Fiddler勾选了“Ignore server certificate errors”它不会检测服务器证书是否过期或无效。在测试一些用自签名证书的测试环境时这个选项很实用否则Fiddler会直接断开连接。但要注意这个选项同时也意味着Fiddler不再对服务器证书做合法性校验在不受信任的网络环境中测试时风险较高用完记得关掉。5.2 Android 7.0以上抓不到HTTPS明文前文提到Android 7.0之后应用默认不信用户证书。不管是Fiddler还是其他主流抓包工具遇到的都是同一个问题这不是证书装错了是系统信任模型变了。如果你在调试自己开发的应用最简单的方式是在AndroidManifest里指定一个networkSecurityConfig在其中允许信任用户证书。如果是调试第三方App就只能用Android 6.0模拟器或者Root后的真机。这些方案我都验证过Android 6.0模拟器是复现成本最低的一个我至今仍留着两台不同版本的模拟器镜像专门用来做这类抓包实验。5.3 手机连上代理后无法访问网络手机设置代理后出现大面积“无法连接到服务器”的情况绝大多数不是代理配置的问题而是证书出了问题。最常见的原因是系统时间不准确导致Fiddler签发的证书被认为不在有效期内。解决办法是先让手机时间与网络时间同步再重新下载安装证书。另外如果你在电脑上重装过Fiddler根证书实际上是重新生成了一颗手机上装的是旧证书这时也必须重新下载新证书。旧证书和新证书不同而手机依然在信任旧证书的签名新证书的签名对不上就会握手失败。我之前重装Fiddler后手机抓包直接全部失败排查了半小时才想起来是证书没更新。5.4 Fiddler卸载后电脑上不了网这个问题的原理和代理残留有关。Fiddler在运行时会修改Windows的WinINET代理设置把流量指向本机8888端口。正常情况下退出Fiddler时会自动把代理设置恢复原样。但如果你强制结束进程或者Fiddler崩溃退出代理设置就残留下来了指向的8888端口却没有任何程序在监听于是所有浏览器的请求都发不出去表现就是“上不了网”。解决办法也很简单打开Windows的“Internet选项 - 连接 - 局域网设置”找到代理服务器区域把“为LAN使用代理服务器”的勾选去掉或者点击“高级”把里面的代理清空问题立刻恢复。这个坑在网上被问得极多其实就是代理设置残留的问题知道原理之后两分钟就能解决。我这里做一个简短的速查表便于日常遇到问题时快速定位现象优先排查方向处理办法浏览器HTTPS报警告证书信任位置不对确认证书在受信任根证书颁发机构HTTPS抓不到任何请求解密开关未打开勾选Capture HTTPS CONNECTs和Decrypt HTTPS traffic手机装证书后抓不到App流量Android 7.0信任策略换Android 6.0模拟器或Root后装系统证书手机连代理后无法访问系统时间或证书不一致同步时间重装Fiddler证书卸载Fiddler后无法上网系统代理残留关闭LAN代理设置只看到CONNECT请求证书未完整信任在系统证书信任设置中开启完全信任尤其iOS5.5 抓包中的三个细节心得最后分享几个实操中积累的细节心得都是文档不会写但实际特别有用的经验。第一抓包时最好把浏览器的缓存关掉否则重复请求可能直接命中缓存Fiddler里根本看不到新的网络请求。Chrome按F12打开DevTools勾选Network面板的“Disable cache”能有效排除干扰。第二在微服务或前后端联调场景下与其在Fiddler的会话列表里手动翻找某个请求不如直接用Fiddler右上角的过滤器Filters按域名或URL关键字过滤尤其流量大的时候这个操作能帮你省下大量时间。用好过滤器比会一百个快捷键都实在。第三Fiddler虽然很适合调试HTTP/HTTPS但如果要分析TCP层重传、TLS握手包细节这类底层问题它的能力就有限了这时候应该换Wireshark配合浏览器导出的密钥日志来做。工具没有绝对的优劣关键是用对地方。我自己的习惯是调业务接口用Fiddler查网络协议问题用Wireshark两侧互补基本能覆盖日常所有需求。我在实际使用中还有一个体会Fiddler这套“中间人代理”机制不只是一个工具原理更是一把理解网络安全体系的钥匙。搞明白了证书信任链、搞明白了为什么随意信任根证书是危险行为你对HTTPS的理解深度会明显超过那些只是“会抓包”的人。以后再碰到各种抓包、证书、加密相关问题你会有一种“见山不是山”的清晰感。后面有时间我打算再写一篇关于如何用FiddlerScript做自动化抓包与断言校验的文章那是另一个可以深挖的方向。