为什么我抓不到baidu的数据包?

转自:小白debug
最近,有位读者问起一个奇怪的事情,他说他想抓一个baidu.com的数据包,体验下看包的乐趣 。
但却发现“抓不到”,这就有些奇怪了 。
我来还原下他的操作步骤 。
首先,通过ping命令,获得访问baidu时会请求哪个IP 。
$ ping baidu.com
PING baidu.com (39.156.66.10) 56(84) bytes of data.
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=1 ttl=49 time=30.6 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=2 ttl=49 time=30.6 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=3 ttl=49 time=30.6 ms

从上面的结果可以知道请求baidu.com时会去访问39.156.66.10
于是用下面的tcpdump命令进行抓包,大概的意思是抓eth0网卡且ip39.156.66.10的网络包,保存到baidu.pcap文件中 。
$ tcpdump -i eth0 host 39.156.66.10 -w baidu.pcap
此时在浏览器中打开baidu.com网页 。或者在另外一个命令行窗口,直接用curl命令来模拟下 。
$ curl 'https://baidu.com'
按理说,访问baidu.com的数据包肯定已经抓下来了 。
然后停止抓包 。
再用wireshark打开baidu.pcap文件,在过滤那一栏里输入http.host == "baidu.com"
此时发现,一无所获 。

为什么我抓不到baidu的数据包?

文章插图
在wireshark中搜索baidu的包,发现一无所获
这是为啥?
到这里,有经验的小伙伴,其实已经知道问题出在哪里了 。
为什么没能抓到包
这其实是因为他访问的是HTTPS协议的baidu.com 。HTTP协议里的Host和实际发送的request body都会被加密 。
正因为被加密了,所以没办法通过http.host进行过滤 。
但是 。
虽然加密了,如果想筛选还是可以筛的 。
HTTPS握手中的Client Hello阶段,里面有个扩展server_name,会记录你想访问的是哪个网站,通过下面的筛选条件可以将它过滤出来 。
tls.handshake.extensions_server_name == "baidu.com" 
为什么我抓不到baidu的数据包?

文章插图
 通过tls的扩展server_name可以搜索到baidu的包
此时选中其中一个包,点击右键,选中Follow-TCP Stream
为什么我抓不到baidu的数据包?

文章插图
右键找到tcp 流
这个TCP连接的其他相关报文全都能被展示出来 。
为什么我抓不到baidu的数据包?

文章插图
HTTPS抓包
从截图可以看出,这里面完整经历了TCP握手和TLS加密握手流程,之后就是两段加密信息和TCP挥手流程 。
可以看出18号和20号包,一个是从端口56028发到443,一个是443到56028的回包 。
一般来说,像56028这种比较大且没啥规律的数字,都是客户端随机生成的端口号 。
443,则是HTTPS的服务器端口号 。
 
HTTP用的是80端口,如果此时对着80端口抓包,也会抓不到数据 。
 
粗略判断,18号和20号包分别是客户端请求baidu.com的请求包和响应包 。
点进去看会发现URL和body都被加密了,一无所获 。
那么问题就来了 。有没有办法解密里面的数据呢?
有办法 。我们来看下怎么做 。
解密数据包
还是先执行tcpdump抓包
$ tcpdump -i eth0 host 39.156.66.10 -w baidu.pcap
然后在另外一个命令行窗口下执行下面的命令,目的是将加密的key导出,并给出对应的导出地址是/Users/xiaobaidebug/ssl.key
$ export SSLKEYLOGFILE=/Users/xiaobaidebug/ssl.key
然后在同一个命令行窗口下,继续执行curl命令或用命令行打开chrome浏览器 。目的是为了让curl或chrome继承这个环境变量 。
$ curl 'https://baidu.com'


推荐阅读