Bilibili直播弹幕抓取(2):Fiddler与WireShark

前言

上次提到了 Bilibili 的弹幕传输是基于 WebSocket 的二进制帧,因此给调试带来了一定不便。

但是 WebSocket 归根到底还是 TCP,并且我们已经知道它的帧结构了,剩下的就是抓包了。

这里提供三种方法:websocket-monitor, Fiddler, WireShark。

websocket-monitor

websocket-monitor 是 FireFox 的一款插件,它是由大名鼎鼎 Firebug 开发团队开发的。

不过不幸的是它只支持到 FireFox 57,在我的电脑上 FireFox 的版本号是 59,所以我没法使用它,但是从截图来看应该是一个很不错的插件。

这也是为什么标题中没有它(笑)。

Fiddler

Fiddler 其实是一款 HTTP 层面的网络调试器,按理来说它应该没有能力调试 WebSocket,因为 WebSocket 只有握手的时候才会使用 HTTP。

不过事实上从 Fiddler 4.5 之后 Fiddler 就内置了调试 WebSocket 的功能,非常方便。

只要双击最初握手的 HTTP 包,切换到 WebSocket 选项卡即可:

从图中可以看出 Fiddler 支持多种形式解析数据,由于弹幕数据是用 JSON 传输的,因此我们正好可以用 JSON 看到数据。

WireShark

相比 Fiddler 来说,WireShark 就要底层的多了,它甚至可以用来抓链路层的包,对于 WebSocket 这种基于 TCP 的包自然也是不在话下。

不过稍微有点麻烦的是,Bilibili 采用的是 wss,即 Secure WebSocket。和 HTTPS 类似,它采用了 SSL/TLS 加密,因此在用 WireShark 抓包的时候我们只能看到加密后的数据,要解密的话需要相应的 key。

好在浏览器为我们提供了一项功能是 key logs,利用这个功能就可以让 WireShark 自动解密。

首先我们设置环境变量 SSLKEYLOGFILE 为存放 key logs 的路径,比如在 Windows 下:

重启浏览器就可以看到文件中有内容了,然后我们需要设置 WireShark 让它自动读取这个文件,在首选项中选择 Protocols->SSL-> (Pre)-Master-Secret log filename 设置为刚才环境变量中的路径即可。

WireShark 默认会捕获所有链路层、网络层和传输层的包,所以如果不过滤的话根本没法找到想要的包。

由于之前在 Chrome 摁 F12 看见 WebSocket 走的端口是 2245,所以这里使用的条件是 tcp and tcp.port == 2245

可以看到所有的包都被筛选出来了。

这时候只要在任意一个包上双击,在弹出的页面中可以看到下面有一个 Decrypted SSL,其中就是解密后的内容了。

这里中间的昵称和弹幕内容等都是 UTF-8 编码的,但是 WireShark 并没有检测出编码,只显示了 ASCII 字符。

小结

到这里其实调试就非常简单了,个人推荐采用 Fiddler 调试,相当灵活和简单。

下一节就是真正分析 Bilibili 弹幕传输协议了,不过实际上我才用了一种非常偷懒的办法(逃。

参考资料

What’s New in Fiddler 4.5 发现新大陆:一个最简单的破解SSL加密网络数据包的方法 NSS Key Log Format

后记

一开始使用 Fiddler 的时候不知道可以直接调试 WebSocket,果断写了 FiddlerScipt 结果最后倒在了编码问题上。

核心原因是 FiddlerScipt 本质是 JScipt.NET,所以它的 char 是双字节的,我把每个字节读入后转为 char 就直接导致 UTF-8 编码的文本 double encoded——当然,这是我卡了很久才发现的。

不过也算是复习了一下 UTF-8 编码规则吧,以后再见到 C2 C3 就有“二进制直觉”了吧(苦笑)。