您的位置:首页 > 其它

《锅来了!!!不要慌~~~》——那些你应该知道的知识(一)

2018-08-27 01:36 1591 查看

卿本神工,奈何背锅,明辨真相,且看本章—

《锅来了!!!不要慌~~~》

#####################################################################################################

写在前面:本文部分内容来自CSDN其他博客,在此声明并表示感谢。

#####################################################################################################

事件背景

近期有一个业务,因IPS的加入而受影响,将IPS置为Bypass状态后,业务恢复。判断IPS对相关报文进行了阻拦。在此基础上,通过在F5上抓包,获得业务可用情况下,数据包信息。以该数据包为例,总结一下抓包中的各项数据信息。

首先,我们通过wireshark打开数据包,wireshark默认显示Time Source Destination Length Info这几项信息,由于判断数据包是否被正常的发送和接受,我们一般通过Sequence Number和Ack来判断,于是在此基础上,增加Sequence number、ack number和TCP Segment Len。增加方法为选中相应的字段-》右击-》增加为列。

#####################################################################################################

分析过程经验总结:

首先,我们要通过抓包判断故障的原因,首先应能够准确定位业务发生故障的部分和我们抓取的数据包哪一部分对应。

windows可以通过netstat -ano 找到PID,在通过tasklist|findstr 3280 命令找到对应的服务。通过服务找对应的端口号也是同理.

linux可通过natstat -nap|mor,查看(未证实)

通过以上方法判断相应进程和所使用的的源目端口后,在数据包中找到对应的TCP源目回话,通过追踪TCP流,只看与该回话相关的数据包,排除其他干扰。

如果无法准确定位,只能通过wireshark的分析,看数据包异常部分,再追踪TCP流。

#####################################################################################################

分析过程知识总结:

本部分解释TCP数据包的发送和接受过程,如何判断数据包之间的关联关系。

通过wireshar打开数据包,追踪TCP流后,可以发现,这是一个TCP连接,进一步分析,这是一个SSL相关应用。客户端通过高位端口46929与对方端口443建立连接,应该是访问对方的https网站或接口。其中SSL连接建立的过程较为复杂,在此不做展开分析。如果以后碰到SSL建立连接异常的话,可通过次案例进行对比分析。

在此声明,wireshark中显示的sequence number和ack number并非真实的相关序列号,而是相对的序列号。相对序列号从0开始,这便于进行数据包的分析。

从图中可以看出,源地址10.200.x.x与目的地址101.89.x.x建立TCP连接。

##########################################################################

TCP的三次握手

首先是TCP的三次握手,原理如下图:

在本次案例中,wireshark显示为相对序列号,x=0,y=0。所以我们看到的是SYN包,seq=0,ack=0。SYN ACK包,seq=0,ack=1.ACK包,seq=1,ack=1。

之后开始应用层数据的传递,见下图。

############################################################################

MTU与MSS

其中,TCP Segment of a ressembled PDU表明这是一个被切片的数据包。在TCP握手协商过程张,会协商MSS(Maximum Segment Size)。见下图:

可见,本次协商出的MSS值为1440字节。这个数据是怎么计算出来的呢?

最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议承载上层数据报文的最大数据报大小(以字节为单位)。最大传输单元这个参数通常与通信物理接口有关(以太接口、串口、ATM、E1/T1等)。通常来说是指在IP层上能通过的最大报文长度。

在IP协议中,一条传输路径的“路径的MTU”被定义为从源地址到目的地址所经过“路径”上的所有IP接口的MTU的最小值。RFC 1191描述了“路径最大传输单元发现方法”。在这项技术中,源地址将数据报文的DF“Don't Fragment”标记位置位,路径上任何需要将报文进行分片的设备接口都会将这种数据报丢弃并返回一个“数据报过大”的ICMP响应到源地址,并在这个响应中告知了该接口的MTU值。这样,源主机就“学习”到了不用进行分片就能通过这条路径的最大传输单元了。

在以太网上,以太网接口缺省的MTU为1500(最大传输单元,这是考虑到早起10M带宽网络中的传输效率计算出来的),注意这是一个缺省值。所以以太网最大帧长应该是以7字节前导同步码+1字节帧开始定界符+6字节目的mac+6字节源mac+2字节帧类型+1500+4字节FCS=1526bytes。 (FCS:Frame Check Sequence(帧校验序列),俗称帧尾,即计算机网络数据链路层的协议数据单元(帧)的尾部字段,是一段4个字节的循环冗余校验码,CRC。)

在电脑上,通过抓包软件进行抓包,抓到的是去掉前导同步码、帧开始分界符、FCS之外的数据,默认情况下是1526-7-1-4=1514字节也就是6字节目的mac+6字节源mac+2字节帧类型+1500=1514bytes。

而MSS=MTU-TCP头部大小-IP头部大小=1500-20-20=1460bytes。

可以用ping -l 1472 -f IP地址 来探测,路径中协商的最小mtu。这里设置了ping不允许分片,若1472可以ping通,1473不能ping通,则MTU=1472+28=1500bytes,其中28为icmp包的ip头长度。一般的ip头长度为20.

在我们这个例子中MSS值为1440字节,可见在路径中,最小的MTU=1480bytes。

这个值可以在wireshark中看到,找到一个分片的数据包,见下图:

其中IP层的Totol Length为1480,等于我们上文分析的MTU的值。

#################################################################

Sequence Number与Acknowledge Number

关于Sequence Number:简单来讲,用来记录一端作为发送者一共发送了多少字节的数据包,告诉结接受者我之前已经发送过多大字节的内容了。针对发送者,在之前未发送携带有有效数据的数据包,或第一个发送携带有有效数据的数据包时,seq将维持不变。只有从第二个发送携带有有效数据的数据包开始,seq=原seq+上一次发送的数据包的tcp Segment length。

所以Sequence Number只有在自己发送携带有有效数据的数据包是,才会增加。

关于Acknowledge Number:简单来讲,用来记录一端作为接受者告诉发送者我一共收到了多少字节的数据包,进行确认。作为有效数据包的接受者,用来返回,告诉发送者我一共收到了多少数据。所以ack=原ack+发送者发送的数据包的tcp Segment length。所以,我们要确定接受者返回的ack数据包哪个是用来响应发送者的数据包,需要通过期返回的ack的值来判断。

通过上面的总结,我们可以发现Sequence Number记录着发送者之前发过了多少数据,Acknowledge Number记录着接受者接到了多少数据。

很多人通过确认包的Seq No=发送包的Ack No来寻找其中的对应关系,这同样可以解释的通。因为此次发送数据包一端的ack记录着他之前接受到了对端发来的多少数据,这也就等于对端一共发了多少数据,而这个数据等于下一次对端返回的确认包中的Seq No.

而ACK确认包中的Ack No.可以推算出=发送者之前发送的数据包的量+这次发送的数据包大小。也就是说ACK=发送者发送的数据包的seq+发送者发送数据包的TCP segment Length.

下面针对图中的具体案例进行分析。

为便于解释,在这里将A=10.200.x.x B=101.89.x.x。

  • 146—这是这个TCP流中A发送的第一个携带有效数据的包,发送的有效的数据长度为144,之前的包都没有携带数据,所以seq=1+0=1,之前也没有接收到有效数据,所以ack=1+0=1。

  • 147—B收到该数据包,发送ack包告知我方确认收到上一个包,这是一个单纯的ack包,之前B也没有发送过有效数据。所以seq=1+0=1,ack=原ack+收到的数据包的TCP Segment Length=1+144=145(相当于告知对方受到数据的量)。

  • 148—紧接着,B主动发起Server Hello数据包,这是他第一次发送带有有效数据的数据包,所以seq=1+0=1,没有收到新的数据,ack=145+0=145。

  • 149、150—B继续发送带有有效数据的数据包,同时可以注意到,这是一个TCP分片的数据包,每个数据包携带的有效数据长度为1440字节。所以149包中的seq=1+148包的有效数据长度=1+1440=1441,150包的seq=1441+149包的有效数据长度=2881.这个过程中没有收到A发来的其他数据,所以ack没有变化,维持在145.

  • 151—B继续发送带有有效数据的数据包,所以151包的seq=2881+1440=4321,没有收到新的数据,ack维持不变,ack=145.

  • 152—A向B确认他收到的数据包,152包的seq=146包的seq+146包的有效数据长度=1+144=145。ack=2881,根据分析,ack=2881=1+1440+1440.所以可以判断,这个ACK确认包是回应确认收到第148和149包的。

  • 153—这个过程中A,没有发送其他有效数据(tcp segment length=0),所以seq没有增长,153包的ack=4321=2881+1440,所以这个包使用来确认收到150包的。

  • 154—与之前的分析同理,ack=5243=4321+922,所以这个ACK确认包是用来回应收到151包。至此由B发送的148、149、150、151都被A确认收到。

继续分析,进行巩固,见下图:

  • 155、156、157—这些包都是A发送带有有效数据的数据包给B,seq依次增加,155包seq=145=145+0.156包seq=227=145+82.157包seq=227+6=233这个过程中没有收到B发送的数据包,这个过程ack维持不变。

  • 158、159—这是用来回应确认收到A发送的数据包,可以推理158包用来确认收到155和156包,158包的ack=233=145+82+6。159包的ack=286=233+53.同时注意159包同样携带有效数据,长度为59个字节。要确认这是不是同时是一个ACK确认包,可以通过TCP层的FLAGS判断。如下图

其中ACK:确认标志。确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure-1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。

至此我们应该掌握了关于Sequence Number和Acknowledge Number的计算方法,和数据包的关联关系。

其实也可以通过wireshark里面的分析,直接看到ACK包是对哪个包的确认。如下图:

#####################################################################################################

TCP的四次挥手

TCP四次挥手原理见上图,一般情况下,服务器返回的ACK包和发送的FIN ACK 包可能是同一个包。

关于三次握手和四次挥手的原理,可见CSDN博客,小书go的整理,此文部分图片也是其博客中的内容,在此表示感谢。

https://www.geek-share.com/detail/2707584434.html

#####################################################################################################

针对本次案例的部分解读

本次业务的实际场景是,服务端会发送一个长报文给客户端,那么这个报文有多长呢,下文是相关推断,没有经过仔细验证:

从上图中可以看出来,第163包,确认了收到第162包后,B端开始持续发送数据,这里TCP对数据进行了分片,每个分段的TCP Segment Length=1440.

可以通过wireshark看到分片在哪里结束,如下图:

跳转到第179帧,如下图:

可以看出来,上一次TCP分片,一共分片12段,报文长度为16421.然而第179帧,同样也是一个分片的报文,在第190结束,根据上图的方法,在excel表格中进行统计。

然而这次抓包一共有8519个帧,采用以上的统计方法不现实。

简单来讲,可以看最后一个ack包的ack的值,这代表着他一共接受到的数据的总量。这次抓包中该数值见下图:

8509帧中,ack number=10107598字节,换算成我们常见的单位也就是10107598bytes=9870.70117KB=9.6393566MB。大约为10M不到,这与开发人员的描述相符。

同时可以看到,本次TCP交互,从第一个帧到该帧共耗时2.55秒。这与开发人员描述的大概2秒可以将文件下载下来相符。

###################################################################################################

理想总是美好的,在准备了这么多知识后,下面开始正文

《锅来了!!!不要慌~~~》

本次抓包中存在着部分异常报文,具体见下图,进行简单分析:

TCP Previous segment not captured.

第一个异常报文出现在第1691帧,见下图:

这里,wireshark解读,提示为TCP Previous segment not captured——这是因为wireshark根据Sequence Number发现,没有抓到期待的数据报文。

看第1690帧,seq=1931744,tcp segment length=1440,则1691真的seq应该=1931744+1440=1933144.然而1691帧的seq=1940384.

并且我们可以推断,本次tcp交互协商的mss=1440,则这中间丢了(1940384-1931744)/1440=6,也就是有5个包没有被抓到,他们分别是:

seq=1933184、1934624、1936064、1937504、1938944的这几个包。记住这串数字,他们之后还会出现。

这意味着在一个被分片的长报文中,有的数据包没有被接收到,由于此次是在F5上抓包,相当于处在报文转发的中间路径上。那么这几个包没有被抓到,可能是网络在中间丢了,也可能是wireshark本身没抓到,也可能是服务器还没有发,可能是中间网络延时比较大等等,可能性很多,这个时候网络基本把锅背起来了。

下面的1694帧也是相同情况,经过计算,中间也是差了7个包。我们继续往下看:

这时B端,服务器端还在继续发送数据,A端有时会回应ACK,表示收到了哪些数据。

从图中可以看出,1695帧回应的是1688帧。1698帧回应的是1690帧,也就是出现分片没有被抓取到的前一个帧。而之后由于TCP分片发送的混乱,客户端不再更新确认收到的数据,也就意味着ACK No.不再增长,于是便出现了Dup ACK。

这里我们注意到这里有TCP option出现,在这个例子中是SACK。

SACK

SACK是用来回复告诉发送者有哪些包没有被确认接受,在下图中:

A告诉B,我已经从你那边收到1933184的数据,这个值等于1933184=1931744+1440,是来请确认1690帧的。

然而根据我们前文的分析,我们此次抓包并没有抓到seq=1933184的数据包,而此时客户端确告诉服务器我已经从你那边接收到了1933184的数据帧,由此,wireshark判断,这一次数据传递中出现了乱序,也就是TCP-out-of-order.

除此之外A告诉B,有seq=1940384到1944704,3个包还没有被确认。我们结合上文的分析来看

这是由于1933184 到1938944这5个包没有被客户端收到,所以之后的1940384开始的数据包也不被服务器确认收到。到这里我们感觉开始找到了数据包出现乱序的源头。

我们继续往下开,这时服务器B继续向A发送数据,如下图:

1703帧,表示又有一些数据包没有被wireshark抓到,这无疑将进一步加重此次传输的混乱的情况。

TCP Dup ACK

紧接着,来到1704帧,wireshark判断该帧为与1698帧重复的ACK包,然而我们点开进一步分析,发现这仍是一个带有SACK TCP option的数据包。在这个数据包里标记了除了上一个1698帧,表示的还没被确认的包以外,还增加了一段,表示1953344帧到1957663帧,也还没有被确认。由此可见,1704帧与1698帧不是完全相同的,他更新了一些尚未被确认收到的包的信息。从wireshark tcp info中,也表示了这些相关的信息,如下图:

SLE表示SACK中的Seuqence Left Edge。SRE表示Sequence Right Edge。

由此可见,后面大量的wireshark判断为重复ACK的报文,其实都在不停地返回告诉服务器B,有哪些数据还没有被确认接受。这之中由于SACK最多只能标记4个没有被确认接受的片段组,伴随着越来越多的数据没有被确认接受,SACK中能表示仍未被确认的片段也在不断刷新。而这一切的原因都是因为帧1691前有5个数据包,没有被本次抓包抓到。除此以外,每个显示TCP Previous segment not captured的数据包都会进一步加重这个情况。

目前我们继续针对1691前没有被抓到的5个数据包,而引起的的混乱进行分析。我们继续往下看

可以看到,这个情况一直在持续,A不停地发送带有SACK的 报文,更新哪些还没被确认。我们继续向下看,直到一个数据帧引起了我们的注意。

TCP Fast Retransmission

当服务端收到3个或以上重复的ack包时,发送方会假设这个数据包在传输过程中丢失了,就会发送tcp fast retransmission, 其他所有正在传输的数据包都要靠边,直到把快速重传数据包发送出去为止。在我们这个例子中,dup ack已经发了100个...如果收到三个就能成功触发重传的话,可能会对之后的影响小很多。而针对服务端没有收到3个或以上的TCP Dup Ack包的话,只能等待ACK确认报文的超时时间,再发送TCP Transmission数据包。

帧1928,wireshark判断服务器B可能是补发了一个seq为1933184的数据包,这与帧1691中,显示的有几个被分片的包没有被抓到高度吻合。之前的分析见下图:

“”

TCP Out-Of-Order

于是我们可以发现,从1928帧开始,到之后出现的TCP Out-Of-Order的几个报文,是服务器在对之前wireshark在1691帧之前没有抓到的数据包进行重发。

可见,上图中几个数字与前文分析的,没有被抓到的几个数据包的seq号完全吻合。

在帧1928发出后,被客户端在1937帧,确认接收到。见下图:

这个报文确认了seq=1933184的报文被接收到,同样,这才被wireshark认为是正确的,与1698相同的ACK确认包。于是之后便没有了报TCP Dup ACK 1698的报文。随后的几个ACK包依次确认了前面没有被抓到的数据包的报文,分别是1937对应1928、1939对应1931、1942对应1933、1948对应1935和1938。至此引发大混乱开始的5个包,都被确认接受到。

但是由于之后又发生了数据包没有被抓取到和接收端积累了大量的数据仍未发送确认接受,导致ACK包中的SACK始终有值。

再来看一个例子:

在1750帧,显示又有TCP分片没有被抓取到。这包括了(2008064-2005184)/1440=2-1=1,这意味着有1个分片没有被抓到,也就是seq=2005184+1440=206624的数据包。这同样会引起与上文相同的问题,会导致TCP Dup ACK和TCP out of order的出现。具体见下图:

帧1963确认了分片没有被抓取到的前一个帧1748帧,而之后由于TCP分片发送的混乱,客户端不再更新确认收到的数据,也就意味着ACK No.不再增长,于是便出现了Dup ACK。

帧1972的Ack No=2009504=2006624+1440+1440。这意味着帧1972确认了帧1961和帧1750.之后便没有了TCP Dup ACK 1963.

总结一下

抓包中,一旦出现有的TCP/IP分片没有被抓到,也就是TCP Previous Segment not captured的出现。这便意味着接收端存在着没有收到的TCP/IP分片,没有办法对TCP数据包进行重组,提交上端应用层的情况。在这种情况下,发送端仍然会继续发送,接收端仍然会继续接受数据包。当接收端确认了发生分片丢失前的前一个帧以后,由于没有收到完整序列号的tcp分片,则接收端无法确认之后收到的tcp分片,则ACK确认报文中的Ack

 No值不会增长, 但是会通过发送带有SACK这个tcp option的ACK确认包的方式告诉发送端,我收到的包中有哪些包没有被确认接受。这个SACK在变化,Ack No.没有变化的值,会被wireshark认为是TCP Dup Ack。而由于SACK只能记录4组没有被确认接受的数据包,所以SACK中的SLE和SRE是不断滚动递增的。

只有当服务器作为发送端将客户端没有接受到的TCP分片重发,或者也有可能是第一次发送时,这时wireshark会抓到TCP Retransmisson的包,或者是TCP out-of-order的包。只有当接收端回复ACK确认包,确认收到之前没有抓取到的TCP分片时,其返回的ACK的Ack No.数字才会增加。wireshark才会认为这个Ack不是Tcp Dup Ack

由于在本例子中,这个TCP报文传输的数据量大约有10MB,这中间多次出现了TCP Previous Segment not captured。所以导致抓包中有很多的TCP Dup Ack,TCP out-of-order。究其原因,都是因为有的TCP分片在客户端这一侧没有被按照顺序的接收到。至于根本原因后文将会作出猜测。

我们继续向下翻看,直到2096帧,客户端B返回的ACK不再是SACK,代表不再有没被确认的报文。

此时ACK的Ack number=2255744=2083帧中的seq+ack=2254304+1440.

这代表着之前服务器端B发送的数据包都被A收到。

在这之后,wireshark分析的数据包恢复正常。没有再发生TCP乱序、TCP分片顺序混乱等现象。

原因猜测

根据前文的分析,我们知道导致本次TCP数据传输过程混乱的原因是,一个长报文被分片,而一些TCP分片没有被服务端按顺序的发送给接收端,导致出现了很多TCP乱序和Dup Ack等。这对数据包实际的传输速率会造成很大的影响。同时,由于Dup Ack的大量存在,使得IPS误以为这是ACK Flood攻击,将相关报文进行了阻断,进而影响了业务。

关于TCP分片没有被按顺序的送到接收端的原因,也就是TCP Previous Segment not captured出现的原因,这个可能性有很多,现在未证实的情况下作出以下推测。

发送端服务器层面链路层——也就是发送端网卡层面,队列满,导致部分TCP分片的丢失,进而导致部分分片没有被按顺序发送,需要之后的重传。

链路层之间,由于本次抓包是在接收方F5上抓包,而且是与公网的服务器进行交互,中间经过的对端数据中心设备、代理软件、运营商设备等等,都可能导致TCP分片的丢失,或发送的乱序。

在接收端TCP层,本次抓包没有发现win=0的现象出现,判断接收端读取文件的效率不是瓶颈。

综上所述,判断故障主要还是集中在链路层,和链路层中间串接的各类设备上。

至此,本章完。

锅没甩掉?敬请期待下一章

《锅甩了!!!妥妥的~~~》

 

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: