ITPub博客

首页 > > > 遇到紧急问题,不要慌:抓包分析来救你(一)

遇到紧急问题,不要慌:抓包分析来救你(一)

作者:得一技术 时间:2019-09-05 16:35:09 0 删除 编辑

1 案例

有一天,广告业务人员反馈,部分广告位显示空白,如下图所示。

作为开发,想不明白为什么广告位显示空白,而且是选择性空白。于是登入服务器查看广告曝光日志,结果显示所有广告位都有广告。那到底是什么原因导致空白广告呢?

运维也来帮助找原因。运维领导站在后面指挥着运维小兵(紧张压力大,手还发抖),仔细查了半小时,没有发现问题。同时另一个有着抓包分析经验的运维人员也过来帮忙,决定进行抓包,希望能从抓包文件里面捕获到线索。

广告业务人员首先发现广告显示有问题,担心是自己的操作失误导致了问题,所以非常希望能够知道问题的原因。

这三种人的状态分析如下图:

最终通过抓包分析,发现问题是由网关网卡MTU配置不当导致(“广告位空白显示的罪魁祸首:MTU不一致”会有介绍)。

当出现TCP相关问题的时候,抓包分析对于开发、运维、DBA、测试、前端都很重要。

2 哪些场景需要抓包分析?

TCP/IP是互联网应用的基础。作为互联网老兵,我总结出如下场景需要抓包分析:

第一种场景是分析程序运行机制。开发Cetus(数据库中间件,代理MySQL数据库的软件)的过程中,经常需要去分析竞争对手产品的特性,这样有助于自身产品的不断进化,但竞争对手产品(如商业软件数据库中间件OneProxy)未必是开源的,这个时候抓包分析就显得极其重要。通过抓包分析,我们可以研究OneProxy在分布式场景下, SQL是如何代理给多个后端的,以及OneProxy有没有实现流式传输。

第二种场景是挖掘线上潜在问题。例如,开发广告投放系统的时候,利用流量复制工具TCPCopy复制线上广告流量到测试系统,通过抓包查看自己开发的广告投放系统有没有异常的TCP状态,如大量CLOSE_WAIT状态(忘记关闭连接导致的连接泄漏)。开发Cetus的时候,利用TCPCopy复制线上MySQL流量到Cetus测试系统,查看Cetus中间件有没有发送不必要的SQL语句给后端,一旦发现了,就可以及时纠正问题,达到不断优化Cetus的目的。

第三种场景是线上出问题了,利用抓包来捕获问题的线索。例如Cetus部署到阿里云环境,开发遇到了性能慢的问题。通过抓包分析,发现是网络抖动导致应用程序报大量慢日志。

总的来说,抓包分析不仅用于帮助解决问题,而且也可以用于分析软件运行的机制,如没有源代码的软件。有一种说法:“不会抓包分析,如同医生不会使用听诊器“。面对TCP相关问题,如果不会抓包分析,你很难去分析和解决问题。

3 如何抓包?

抓包的好处是可以保留问题的现场,方便后续判断。

那怎么抓包呢?

有了抓包工具,抓包其实很简单。

tcpdump和wireshark是目前最流行的两个抓包工具。

1)tcpdump抓包

tcpdump在Linux服务器领域普遍被采用。对于开发/运维/dba/测试来说,tcpdump抓包主要用如下命令就能解决工作中95%的抓包问题:

tcpdump -i any tcp and port xxx -s yyy -w zzz.pcap -v

参数解释如下:

-i any 从所有网卡设备上抓包

tcp 抓取TCP类型的数据包

and “与”的意思

port xxx 捕获端口为xxx的应用数据包

-s yyy 设置抓包大小为yyy大小,一般在60~1500范围,视情况而定

-w zzz.pcap 抓包数据存放到zzz.pcap,pcap后缀名方便wireshark识别

-v 设置实时显示抓包状况

如果想捕获web 80端口的数据包,命令如下:

tcpdump -i any tcp and port 80 -s 1500 -w web.pcap -v

输入命令,按回车键就开始抓包,如下图。

这里Got为0,代表还没有捕获到任何数据包。

我们执行telnet访问来试验tcpdump的抓包情况。

telnet命令格式是:telnet ip地址 服务端口

执行“telnet 172.17.0.2 80”,即访问172.17.0.2机器的80服务,结果显示Connection refused,代表连接请求被拒绝。

这时tcpdump实时显示已经捕获到2个数据包。

如果要停止抓包,按ctrl +c就可以终止抓包过程,这时tcpdump命令显示内核捕获到了多少个数据包,tcpdump抓到了多少个数据包,丢了多少个数据包,通过这些数据可以判断出抓包的情况。

下图给出一个例子,“2 packets captured”代表捕获了2个数据包;“2 packets received by filter”代表从内核的过滤器里面接收到2个数据包;“0 packets dropped by kernel”代表没有丢包,一般压力不大的场景不会丢包。

抓包的时候需要注意如下事项:

1. 抓包文件不能过大

如果线上压力很大,可利用-c参数限制每一个抓包文件抓取的数据包数量。

2. 设置-s参数大小要合理

除非特殊情况需要,一般设置尽量小。越小,越不容易丢包。分析TCP/IP底层协议,一般只需-s 60即可;分析应用协议短请求,一般设置-s 500即可;分析应用协议大请求或者大响应,需设置-s 1500或者更大;如果是为了TCPCopy回放抓包文件,那就设置最大-s 65535或者-s 0。

3. 最好抓完整TCP交互的数据包

因为连接建立的时候会初始化参数,捕获连接建立过程可以更好地分析问题;如果是为了TCPCopy回放(只需访问服务器的流量),把port改成dst port以降低抓包文件大小。

4. 复杂问题可能需要在多个地方同时进行抓包

例如,同时在客户端和服务器抓包,确认是否被途中的防火墙干扰了。

如果需要进一步研究tcpdump高级功能,请参考官方文档:

http://www.tcpdump.org/

2)wireshark抓包

Wireshark是当今主流的网络协议分析软件,不仅可以截获各种网络数据包,而且能够对数据包进行协议分析。

在windows环境下我们演示如何利用wireshark工具抓包。

打开wireshark,点击“捕获”菜单,如下图:

点击"选项",会显示如下的对话框:

在这里选择需要抓包的接口,如选择"无线网络连接";在接口的捕获过滤器(类似于tcpdump的过滤条件)中,填写上“tcp port http”,即捕获http的数据包;点击开始,wireshark就开始抓包了。

如上图,红色方框显示正在抓包,如果要停止抓包,点击红色方框就能停止抓包过程。

虽然原理差不多,个人推荐在Linux环境下利用tcpdump抓包,因为它更加高效。

4 Wireshark抓包分析基础

在进行具体的抓包分析之前,先讲解常用的wireshark操作。

4.1)注意文件格式

不管是tcpdump抓包还是wireshark抓包,保存文件的后缀名最好为pcap,这样就能被wireshark自动识别为抓包文件。例如下图文件都是pcap结尾,自动就被wireshark识别为pcap抓包文件。

打开这些pcap文件的时候就会以抓包数据文件的格式来解析,如果格式不符合pcap格式,那么打开的时候就会报错。

4.2)分析TCP会话

打开pcap文件后,最常用的操作是跟踪某一个TCP连接会话,查看TCP是如何交互的。在大量抓包数据中,不同TCP会话往往是不相干的,所以只分析有问题的TCP会话,对于找出问题的原因是非常有帮助的。

下图展示了如何利用wireshark命令跟踪某一个TCP会话。在某一行点击右键,弹出如下菜单栏,再点击追踪流,弹出子菜单,其中就有TCP流,点击就可以查看这一行对应的TCP流。

下图是跟踪第五个会话(从0开始算)的情况,可以看出整个TCP会话的过程,分别为:TCP建立连接、TCP传输数据和TCP连接关闭。TCP连接是通过三次握手建立的,也即图中三个数据包组成的,缺一不可。在三次握手过程中,会初始化相关参数,如图中的第一个数据包中的WS = 128,代表客户端的窗口扩大选项window scale为128,而第二个数据包中WS = 256,代表服务器端的窗口扩大选项window scale为256,这个参数对于判断对方接收窗口大小非常关键;TCP传输数据包括传输数据内容的数据包和ack确认数据包,而ack确认数据包对于可靠传输至关重要;连接关闭一般是四次挥手,图中把第二次和第三次合并了,所以只有三个数据包,这样做的目的是可以提升网络传输的效率。具体关闭连接参考“深入浅出连接关闭“,连接关闭的多样性远远不是四次挥手所能表达的。

4.3)尽量分析完整的TCP会话

抓包分析的时候,尽量分析完整的TCP会话,因为TCP会话不完整,有时候会导致误判。

上图由于没有捕获到连接建立过程,导致没有捕获到初始窗口扩大选项(window scale)参数大小,而Wireshark给用户显示的时候,却显示没有错误提示的win=29。不熟悉抓包分析的用户,会误以为对方窗口大小是29,从而可能导致后续判断失误。

这时查看Window size scaling factor(参考上图最下面的箭头),如果是-1,说明上面的win值29是不靠谱的。

4.4)利用时间差信息

利用时间差信息,可以充分挖掘很多隐含的信息。

从上图可以看出三次握手过程中,第一次握手数据包(第一个数据包)和第二次握手数据包(第二个数据包)相差0.015473秒,而第三次握手数据包(第三个数据包)和第二次握手数据包(第二个数据包)时间相差只有54微秒,时间间隔的倍数=0.015473/0.000054=286倍左右。

假设是客户端抓包,收到第二次握手数据包后TCP会很快发送第三次握手数据包,这个时间差一般是非常短的,几十微秒,跟上面符合,因此可以判断出这是客户端抓包。

假设是服务器抓包,从收到第一次握手数据包,到发送第二次握手数据包,经过了15毫秒,这个时间差有点大,而发送完第二次握手数据包到接收到客户端的第三次握手数据包,却只花了54微秒,因此这个假设是不符合经验常识的。

4.5)常用wireshark过滤条件

利用wireshark,往往需要找出含有某些信息的数据包,这时过滤功能就显得尤为重要。例如查找是否含有某一个特定类型的SQL语句,这时该怎么做呢?

首先我们需要知道数据包内容是什么协议的数据包,下图是MySQL数据包,端口是6001。由于wireshark事先不知道6001端口的数据包是什么协议的数据包,所以解析的时候是根据默认的X11协议去解析数据包,但这是不对的。因此,我们需要去设定数据包的协议。

根据下图提示打开“解码为”对话框

打开了“解码为”对话框,再根据下图提示操作:

点击Save。设置完成后,6001端口的数据包,将会采用MySQL协议来解析。

下图显示了刚刚被X11协议错误解析的数据包在设置MySQL协议后,已经被正确解析为MySQL协议的数据包内容。

数据包被正确解析后,采用MySQL的过滤条件来过滤SQL语句。如下图,采用“mysql.query contains "select"”过滤出含有“select”的三个数据包。值得注意的是,这里的过滤条件只能应用于MySQL协议,不同的应用层协议需要使用不同的应用层过滤条件。

为分析应用层数据内容,tcpdump抓包的时候, -s参数设置不能过小,否则,上述过滤条件就不会起作用,从而容易引起误判(例如以为没有此类SQL语句)。

利用TCP参数,还可以查询TCP层指定内容的数据包,比如“tcp.flags.syn == 1”,就能过滤出含有syn标志位的数据包,而这个syn标志位,代表着正在进行三次握手。

“tcp.flags.fin == 1”可以过滤出含有fin = 1标志位的数据包,而fin标志位,代表着正在进行连接关闭的操作。

我们还可以利用tcp.port作为过滤条件。例如,下图的“tcp.port == 13354”,可以过滤出端口为13354的数据包。

我们不仅可以利用TCP信息来过滤数据包,还可以利用IP信息来过滤数据包。下图中,“ip.host == 10.238.7.6”可以过滤出含有IP地址为10.238.7.6的数据包。

我们还可以直接选择某些内容作为过滤条件的方法,比如下图利用IP层的“total length: 51”作为过滤条件,wireshark自动转变成ip.len == 51来过滤出IP数据包长度为51的数据包。

4.6)传说中的三板斧

三板斧的第一个是“时间序列”查看。当我们想分析整个会话传输的过程时,可以利用“统计”菜单下的“TCP流图形”的 “时间序列”来查看整个会话过程(参考下图)。

下图展示了TCP流239的传输情况。图中的横坐标是时间,纵坐标为传输的数据量。数据传输集中在几个时间点。因此,在这几个时间点,数据量传输量大,接近竖线;而其它时间点,数据传输空闲,所以是水平线。此分析图可以帮助我们分析TCP会话的整体传输过程。

三把斧另外一个值得关注的是分析栏目中的专家信息,具体操作如下图。

通过点击专家信息,可以统计出一些可疑的问题,如下图。

不过这些问题也不能全信,毕竟网络状况复杂。可能你们会感到疑惑:专家信息,为什么不能相信呢?

个人总结原因如下:

1. 协议没有更新,解析错误导致的误判

2. 抓包过程中丢包导致的误判

3. 未抓全整个TCP会话导致的误判

4. 协议匹配错误导致的误判

5. Wireshark自身程序的误判

5 抓包分析简单信息推理

5.1)判断哪一端抓包案例

抓包一般可以在如下的地方抓包:

1. 客户端

2. 服务器端

3. 中途设备

如果是客户端抓包,那么客户端的TCP对服务器端的ack确认分为两种情况

1. 快速ack确认,因为只需要经过本机器的TCP/IP协议栈,就可以返回,消耗的时间一般最多只有几十微秒

2. TCP ack延迟确认,这时延迟大概是200毫秒左右,适合于外网应用分析判断

以下图中的TCP会话为例。对于矩形框中的两个TCP数据包,第一个是服务器的响应数据包,第二个是对response的ack确认数据包。计算出这个时间差为15微秒(16.996501-16.996486=0.000015s),这么短的往返时间,只可能是从客户端抓的数据包:因为从网卡接收数据包到TCP回复ack数据包,再到网卡,一般也就几十微秒(除非延迟确认),而传递数据包给服务器端,往往至少是几百微秒,所以判断的时候更倾向于是从客户端抓包。

下面是服务器抓包的案例,我们看看服务器端抓包的时间差有什么规律。

上图中250.217是服务器,前面是三次握手过程。三次握手过程不涉及应用层,是在TCP层完成的,协议处理速度都很快(不会产生延迟确认)。当服务器端收到第一次握手数据包,仅仅过了9微秒,服务器就发送了第二次握手数据包(SYN+ACK数据包)给客户端,而客户端的第三次握手数据包(ACK数据包)过了13440微秒,也即0.01344秒才返回。

如果第二次握手与第一次握手时间间隔非常短(几微秒或几十微秒),可以判断为服务器端抓包。

下图给出在中途设备抓包的一个案例:

上图中,第一次握手和第二次握手相差2毫秒,而第二次握手和第三次握手相差1毫秒,不符合客户端或服务器端的时间差规律。因此,数据包可能在中途设备抓取,如路由器或交换机。

5.2)判断哪一端发生了问题

上图展示了从客户端角度看,服务器端web 80端口发来了reset数据包,客户端本身并没有任何TCP会话异常的问题,这样就排除了客户端的问题。因此,我们缩小了问题的范围。

5.3)判断TCP哪个环节出的问题

上图展示了在数据传输过程中发生了数据包重传(客户端延迟确认导致服务器误判),这样问题的范围限制在了数据传输方面。

6 抓包分析之TCP分析

TCP分析主要包括如下方面:

1. TCP流量控制分析

2. TCP拥塞控制分析

3. TCP性能分析

4. TCP灵异事件分析

这里简要讲述这方面的内容,后续课程会讲更加详细的内容。

6.1)TCP流量控制分析

上图内网环境下,客户端访问MySQL服务器,请求返回大结果集响应,导致客户端TCP来不及接收数据,于是通知服务器端接收窗口win=0。当客户端应用接收了数据以后,再次通知服务器端,客户端TCP接收窗口已经有1078400字节的空间,服务器TCP于是可以继续发送后续数据。

6.2)TCP拥塞控制分析

网络传输不仅有窗口限制,而且还有网络拥塞算法的限制。

下图展示了拥塞控制算法是如何发挥作用的。

图中序号264发送请求到服务器MySQL之前,客户端窗口大小为29312字节,后续MySQL发送了若干响应数据包,中间还夹杂着客户端的TCP ack确认,即使是左边的矩形框中的数据包内容加起来也不足20k,还没有到29312字节,win窗口大小已经变为62080字节大小,不但没有缩小,反而增大了。为什么服务器端TCP没有按照窗口大小传输数据呢?这是因为网络拥塞控制算法在发挥作用,限制了传输速度。

当然如果MySQL上面的TCP(注意是在内网环境),刚开始发送数据激进一点,可以提升MySQL的传输数据的速度。

6.3) TCP性能分析

上图展示了TCP传输过程中的性能问题。数据传输主要发生在三个阶段,最初接收窗口较小(见下图1)导致窗口满,线条相对比较曲折,而后TCP动态增加了接收窗口大小(见下图2),从此TCP接收数据就没有再报窗口满,从上图也可以看出后续线条也比较直。

图1

图2

6.4) TCP灵异问题分析

之前根据时间差信息判断出了抓包是在中途设备进行的,而且中途设备在收到服务器端请求响应的最后一个数据包(时间为19:58:42.559118)后, 短时间(20微秒)就发送了Reset数据包给服务器端,从而关闭了服务器端的TCP连接,而客户端连接却还活着。由于客户端不知道服务器端连接已经被关闭,还继续发送ack确认数据包给服务器,最终造成了用户困扰。

7 建立TCP反馈跟应用程序的关联

下面通过两个案例讲述TCP反馈跟应用程序的关联:

7.1)服务不可用与reset数据包的关系

下图给出一个实际的案例:

从用户的描述来看,用户怀疑到了防火墙或者云主机上边的安全策略导致了问题。用户之所以这样怀疑的原因可能如下:

1. 本地localhost能够访问

此处用户没有描述出来,但用户知道

2. 远程无法访问,但能够ping通

在用户看来网络没有问题

3. 没有理解Reset数据包的隐含信息

4. 没有关注客户端提示Connection refused

用户可能认为refused是安全策略干的事情

用户带给我们如下困惑:

1. 用户描述不准确

telnet ip是客户端telnet服务器端,从上面看好像是服务器端telnet客户端

2. 用户会主观加上判断

判断是安全策略,会起到一定的错误引导

3. 用户会遗漏信息

刚开始没有给出本地可以访问的信息

解决用户问题,应该采用不能全信的态度,如果描述都准确,大部分场合都会朝着正确的方向走,但如果描述不准确或者某一个理解不对,就会往错误的方向走,这样离解决问题的距离越来越远。

客户端TCP接收到Reset数据包,会给上层应用报Connection refused,而telnet 远程ip地址 端口号报Connection refused,意味着远程ip地址的端口服务不存在,可以去服务器上面利用netstat –nlp查看IP地址的端口应用是否存在,需要注意的是不能只看端口,还需要看IP地址是否匹配。最终发现用户只开启了localhost的监听,意味着只有本地才能访问服务,远程无法访问。

我们模拟这样的场景:

上述只监听127.0.0.1的地址,利用netstat –nlp查看如下:

我们开启抓包:

远程访问此服务(远程不能利用127.0.0.1地址访问,因为这是本地回路地址)

完美复现了用户的问题。

在建立连接的时候,建立TCP reset跟应用服务不可用的关系,对问题解决是非常重要的。

7.2)连接不关闭与close_wait的关系

当连接一直不关闭,TCP层会提示什么信息给我们呢?

我们可以演示这一场景:

利用MySQL终端登入MySQL服务器,然后一直不操作,然后在MySQL端将interactive_timeout设置为30秒。由于MySQL客户端一直不操作,MySQL就会关闭这个连接,抓包显示如下:

客户端TCP层对MySQL的关闭数据包进行了确认,但TCP没有去关闭连接,这是因为关闭连接的操作是应用层去做的,这个时候需要等应用层的MySQL客户端主动去关闭连接。由于一直不操作,在客户端利用netstat命令查看(如下图),这个连接的TCP状态变为CLOSE_WAIT了。

这意味着客户端没有关闭连接,导致客户端的TCP状态为CLOSE_WAIT状态。如果很多客户端都没有关闭连接,就会积累很多的CLOSE_WAIT状态,从而可能会导致系统服务不可用。

CLOSE_WAIT状态还会引发一系列诡异的问题,后续课程会详细介绍这方面的内容。

8.分析应用层协议数据

应用层数据分析,需要wireshark具有解析相应协议的能力,而大部分常用协议,wireshark都具备,比如我们常用的HTTP协议,MySQL协议等等。

下图展示了wireshark是如何解析HTTP协议的,这对于查明HTTP协议的问题是很有帮助的,否则如果不能解析,只能查看二进制数据去查明问题。

下图展示了wireshark解析MySQL的场景,MySQL返回错误(1062)。通过下面信息,wireshark解析出了问题的具体原因(重复插入)。

我们利用wireshark,不仅可以去解析了解应用层协议的内容,而且还能去分析应用层的诡异问题。

举下面一个例子:

用户通过MySQL客户端去执行一个带有注释的SQL(见下图),注释的内容要求通过数据库中间件去访问master主库,意味着这个命令要去MySQL主库执行,结果用户发现这条SQL去了MySQL从库执行了,跟用户的意图不匹配。

用户想不明白问题的原因。由于不懂数据库中间件的代码,也不懂得抓包分析,解决这个问题变得非常困难。

其实只要会抓包分析,用户就会很容易解开这个谜团。

我们复现这一场景,并进行抓包分析:

从上图可以看出,发出的SQL根本就没有带有注释/*master*/,而这条SQL是只读请求,根据读写分离原则,读请求是应该去MySQL从库执行,数据库中间件也没有做错,但用户感觉是数据库中间件没有按照他的意思去做,所以这里用户怪错了对象。

分析了抓包文件,指向了问题“MySQL客户端发送请求为什么没有带上注释呢?“,而不是之前用户的问题“为什么数据库中间件没有按照我的意思去做?”。

为什么MySQL没有带上注释,网上一搜索,很快就能得到问题的解,这是因为MySQL要想带上注释,必须加上-c,help解释如下:

再举一个分析应用层协议的例子:

这个案例是为了研究竞争对手商业产品OneProxy的工作原理。既然是商业产品,那就拿不到源代码,因此抓包分析就是一种非常好的分析方法。

我们分析的目的是想查看对于客户端的SQL请求,这个商业产品是如何分发给后端多个数据库的。

客户端发送的SQL如下:

根据下图的信息,来分析一下是如何发送给后端数据库的?

可以看到在14:00:12.277142时间,商业软件OneProxy接收到了用户的SQL,在14:00:12.277280这个时间Oneproxy发送请求给第一个后端数据库;过了2s左右,OneProxy发送给第二个后端数据库;又过了3s左右,发送给第三个后端数据库;最后又过了2s左右发送给了第四个后端数据库。从OneProxy接收到用户SQL请求到把请求都发送出去,过了将近7s,可见这种串行工作方式效率是比较低下的。

OneProxy对免费用户提供了这样一个服务,当然如果想提升性能,需要去购买商业版本,这种做法其实是一种商业策略。

通过抓包分析,我们了解了商业产品OneProxy在免费用户模式下的工作原理,可见抓包分析对于分析一个服务器软件的运行机制是非常有帮助的。

9 总结

本讲简单讲述了如何抓包分析,掌握了本讲的内容可以解决一般TCP相关的问题,但对于解决高难度问题还是不够的,下一讲将讲述数据包是如何穿越各层协议的,这对于提升解决TCP相关问题的能力是非常重要的。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69935868/viewspace-3127204/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-07-25

  • 博文量
    16
  • 访问量
    11257