HTTPS加密原理与Fiddler中间人抓包实战:从证书信任到流量解密
2026/9/14 18:18:27 网站建设 项目流程

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体系。服务器运营方会向证书颁发机构(CA,Certificate 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站点发起请求,流程会变成这样:

客户端的请求先到达Fiddler,Fiddler收到客户端发来的ClientHello后,不回真正的服务器证书,而是动态生成一张以目标域名为CN的“伪造证书”,用Fiddler自己的根证书私钥来签名,然后把这张伪造证书发给客户端。客户端校验证书时,发现它是由已受信任的Fiddler根证书签发的,于是通过验证,认为“这是可信的服务器”,接着完成与Fiddler之间的TLS握手。与此同时,Fiddler又作为客户端,与真正的服务器建立另一条TLS连接,用真正的证书完成握手和验证。

之后就是两条平行的加密通道:浏览器与Fiddler之间一条,Fiddler与真实服务器之间一条。浏览器发给服务器的数据,先用浏览器与Fiddler约定的密钥加密,Fiddler收到后解密看到明文,再重新用另一把密钥加密后转发给服务器。反过来也一样。

这就是经典的中间人攻击(MITM)流程。Fiddler不是破解了HTTPS,而是利用了“客户端信任了可自定义根证书”这个前提,重新建立了两段独立的加密通道。严格来说,HTTPS协议本身并没有被攻破,真正被攻破的是客户端对“根证书信任列表”的防线。这也是为什么你在给手机装Fiddler证书时,系统会弹出一堆风险警告——它确实是一个极度敏感的操作。

3.3 两条连接各自的密钥,为什么能还原出明文

很多人会问:Fiddler解密后,它怎么知道怎么解?答案很简单:因为每段TLS连接的主密钥(Master Secret),Fiddler自己都持有。

在客户端与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请求证书未完整信任在系统证书信任设置中开启完全信任(尤其iOS)

5.5 抓包中的三个细节心得

最后分享几个实操中积累的细节心得,都是文档不会写但实际特别有用的经验。

第一,抓包时最好把浏览器的缓存关掉,否则重复请求可能直接命中缓存,Fiddler里根本看不到新的网络请求。Chrome按F12打开DevTools,勾选Network面板的“Disable cache”,能有效排除干扰。

第二,在微服务或前后端联调场景下,与其在Fiddler的会话列表里手动翻找某个请求,不如直接用Fiddler右上角的过滤器(Filters)按域名或URL关键字过滤,尤其流量大的时候,这个操作能帮你省下大量时间。用好过滤器,比会一百个快捷键都实在。

第三,Fiddler虽然很适合调试HTTP/HTTPS,但如果要分析TCP层重传、TLS握手包细节这类底层问题,它的能力就有限了,这时候应该换Wireshark,配合浏览器导出的密钥日志来做。工具没有绝对的优劣,关键是用对地方。我自己的习惯是:调业务接口用Fiddler,查网络协议问题用Wireshark,两侧互补,基本能覆盖日常所有需求。

我在实际使用中还有一个体会:Fiddler这套“中间人代理”机制,不只是一个工具原理,更是一把理解网络安全体系的钥匙。搞明白了证书信任链、搞明白了为什么随意信任根证书是危险行为,你对HTTPS的理解深度会明显超过那些只是“会抓包”的人。以后再碰到各种抓包、证书、加密相关问题,你会有一种“见山不是山”的清晰感。后面有时间,我打算再写一篇关于如何用FiddlerScript做自动化抓包与断言校验的文章,那是另一个可以深挖的方向。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询