本文作者:牧毅,转自知乎,原文链接

背景

写代码是很舒服的一件事情,但是作为一个前端开发,通常还是会有很多的时间会去调试一些代码。

对于一些小型的项目,它们的环境很容易搭建,本地搭个环境跑起来,基本也就足够用了。然而,对于一些大型的项目,就没有那么方便了,基本别指望在本地能把整个项目跑起来。

这时候如果我们改了其中一个 js, 那么该怎么调试呢?

很容易能想到一个方法:我们要是把这个 js 的请求重定向到我们本地修改的那个就好了,这样我们就能直接在线上调试了,本地只要跑个构建脚本就行了。

没错!现在有不少工具可以来做这个事情:

  1. Chrome DevTools 就可以做这个事情;
  2. 有不少插件可以更方便地做这个事情,如: Resource Override 插件ReRes 插件;
  3. Windows 下还可以用 Fiddler — 良心之作,笔者之前一直都用这个,这么好用居然还是免费的!
  4. MacOS 下不差钱的可以用 Charles.

最近呢,笔者换工作了,公司配的是 MBP, 这就尴尬了,没有 Fiddler 用了 o(╥﹏╥)o

插一句,有木有想换 MBP 的童鞋,欢迎来投简历:阿里南京 2019 秋招季/社招,诚邀加入~

Chrome DevTools 还是功能有点弱。Charles 是用不惯的。Resource Overrides 这种扩展虽好,但是它是通过 30X 重定向来搞的,所以呢 HTTPS 的资源重定向到 HTTP 的时候结果会报错……

Whistle 的功能和原理

终于,今天的主角 Whistle 登场了~

Whistle 的定位就是一个 『跨平台web调试代理工具』,可以用来查看、修改HTTP、HTTPS、Websocket的请求、响应。

它的原理其实很简单,不是像 wireshark 一样直接在网卡上抓包,而是像 Fiddler 的代理模式 :

  1. Whistle 自己会启动一个代理服务器;
  2. 我们自己需要配置下浏览器的代理走它的代理服务器;
  3. 然后 Whistle 就在代理的同时把 HTTP/HTTPS 的报文都给顺道截获了,当然像 Resource Override 一样顺手改改报文也不在话下了。

有人问 HTTPS 不是加密了吗?怎么也能截获?

这个问题问得好,原则上来说,HTTPS 的密文在代理服务器上是不能解密的;但是,有一种方法叫『中间人攻击』,通过这种方式,Whistle 就能将 HTTPS 的密文解密掉。

当然,这里澄清下,这种方式虽然是叫『中间人攻击』,但是也是要我们配合下 Whistle 才能行得通。Whistle 本身并不是恶意软件。

安装 Whistle

有木有想要迫不及待地想来试用下 Whistle 了呢?别着急,先安装下。

Whistle 是用 node.js 开发的,所以包是在 npm 上,可以用 npm 来安装:

> npm install -g whistle

当然,国内的话,建议使用淘宝的镜像:

> npm install whistle -g --registry=https://registry.npm.taobao.org

安装完后,会有两个可执行文件:whistle 和简写 w2.

可以看看其基本命令:

> w2 help

  Usage: w2 <command> [options]

  Commands:

    status              Show the running status of whistle
    use/add [filepath]  Set rules from a specified js file (.whistle.js by default)
    run                 Start a front service
    start               Start a background service
    stop                Stop current background service
    restart             Restart current background service
    help                Display help information

  Options:
  ...

启动 Whistle

启动命令如上面的 help 所展示的,有两个:

  • w2 run 是前台运行;
  • w2 start 是作为一个后台服务来运行。

比如说,我们先来前台运行吧:

前端调试利器 Whistle安装使用-冯金伟博客园

这提示得相当详细了,我们就按照提示打开 127.0.0.1:8899/ 即可看到 Whistle 的操作界面。

不同于 Fiddler 和 Charles 这种原生的界面, Whistle 采用了 Web 页面的方式来做 UI, 这也是我喜欢它的原因之一,简洁,省了 UI 的开销。

配置 HTTPS

现在很多应用都 HTTPS 化了,如果要调试这些应用,免不了就要对 HTTPS 的资源进行处理。而在上面也提到了,Whistle 是利用『中间人攻击』的原理来抓 HTTPS 的报文的。所以呢,这里我们需要来信任下我们的中间人(Whistle)的根证书。

根证书在哪儿呢?在刚才打开的 127.0.0.1:8899/ 的页面顶部,有个 HTTPS 按钮,点一下,会出来弹出框。

前端调试利器 Whistle安装使用-冯金伟博客园

弹出框如下图,点击 “Download RootCA” 即可下载。Whistle 还贴心地准备了一个二维码方便在手机上下载这个根证书。

前端调试利器 Whistle安装使用-冯金伟博客园
红色部分请忽略,防止二维码自动识别 :(

然后,就是把这个证书设置成信任的就行了。

具体设置的方法,可以直接参考这个:安装跟证书

到这里安全意识强的童鞋脑子里忍不住有个问题:怎么可以就这么轻易地信任了这个根证书?

对于这个问题,其实主要在于两点:

  1. 这个根证书怎么来的?
  2. 谁能拿到这个根证书?

对于第一个问题,通过查看 Whistle 源代码,我们可以发现其实就是在 lib/https/ca.js 的 createRootCA() 函数中创建的。具体而言,是通过 node-forge 这个 HTTPS 的库创建的。

创建后根证书会默认存储到 ~/.WhistleAppData/.whistle/certs 目录下:

前端调试利器 Whistle安装使用-冯金伟博客园

第二次启动 Whistle 的时候,根证书默认就取存储的根证书 — 当然,如果你觉得这个根证书不安全了(比如被泄露出去了),那你可以把这里的根证书删掉,Whistle 在启动的时候会自动再创建。

对于第二个问题,笔者目前没有发现 Whistle 有上传根证书的行为,但是,这个根证书默认的位置是固定的,所以所有有访问这个存储目录权限的用户/程序都可能拿到这个根证书。

安全提示:

建议启动 Whistle 时通过 -z 或 –certDir 参数来更换证书的存储目录,或者使用单独的账号来启动 Whistle ,并限制证书的存储目录的访问权限。

此外,建议定期更换证书 — 删掉这里的证书,然后重启 Whistle.

配置资源重载

打开 127.0.0.1:8899/#,首先来配置一条最简单的规则:

前端调试利器 Whistle安装使用-冯金伟博客园

这代表把 https://example.com/ 的应答直接替换成 baidu.com/ 的。

点击【保存】来保存下这个配置,然后配置 Chrome (当然其他浏览器也一样) 的代理是 127.0.0.1:8899

接着,用 Chrome 打开 example.com/,O(∩_∩)O哈哈,百度出现了~

前端调试利器 Whistle安装使用-冯金伟博客园

同理,要替换 js 也是类似的操作。

比如一个常见的场景,线上 React 报错了 “Uncaught Error: Minified React error…”, 怎么办?这时我们可以把线上的这个 React 替换成 development 的同版本的 React:

https://xxx.com/js/react-v16.5.min.js https://unpkg.com/react@16.5.2/umd/react.development.js

这样,我们就能看到 React 具体报的啥错啦。

前端调试利器 Whistle安装使用-冯金伟博客园

当然,Whistle 不光可以把 HTTPS 资源重载成另一个 HTTPS 资源,事实上 HTTP -> HTTPS, HTTPS -> HTTP 都是支持的。甚至本地文件也是支持的 — 使用 file:///path/to/your/file.js 即可。所有支持的替换方式可以参考下这里的协议列表:

前端调试利器 Whistle安装使用-冯金伟博客园

更厉害的是,如果配置的规则两边都只是域名,比如

aaa.com bbb.com

那么 aaa.com 域名下的所有的请求都将替换成 bbb.com 的请求 — 有木有种感觉像是 nginx 的反向代理。

后记

Whistle 的功能真的好强大,用起来很方便,还有好些个功能笔者精力有限这里就不一一介绍了…… 敬请探索。