Open dafang opened 10 years ago
TCP/IP通过三次握手建立一个连接。这一过程中的三种报文是:SYN,SYN/ACK,ACK。
第一步是找到PC发送到网络服务器的第一个SYN报文,这标识了TCP三次握手的开始。 如果你找不到第一个SYN报文,选择Edit -> Find Packet菜单选项。选择Display Filter,输入过滤条件:tcp.flags,这时会看到一个flag列表用于选择。选择合适的flag,tcp.flags.syn并且加上==1。点击Find,之后trace中的第一个SYN报文就会高亮出来了。
注意:Find Packet也可以用于搜索十六进制字符,比如恶意软件信号,或搜索字符串,比如抓包文件中的协议命令。
一个快速过滤TCP报文流的方式是在Packet List Panel中右键报文,并且选择Follow TCP Stream。这就创建了一个只显示TCP会话报文的自动过滤条件。 这一步骤会弹出一个会话显示窗口,默认情况下包含TCP会话的ASCII代码,客户端报文用红色表示服务器报文则为蓝色。
窗口类似下图所示,对于读取协议有效载荷非常有帮助,比如HTTP,SMTP,FTP。
更改为十六进制Dump模式查看载荷的十六进制代码,如下图所示:
关闭弹出窗口,Wireshark就只显示所选TCP报文流。现在可以轻松分辨出3次握手信号。
注意:这里Wireshark自动为此TCP会话创建了一个显示过滤。本例中:(ip.addr eq 192.168.1.2 and ip.addr eq 209.85.227.19) and (tcp.port eq 80 and tcp.port eq 52336)
SYN报文:
图中显示的5号报文是从客户端发送至服务器端的SYN报文,此报文用于与服务器建立同步,确保客户端和服务器端的通信按次序传输。SYN报文的头部有一个32 bit序列号。底端对话框显示了报文一些有用信息如报文类型,序列号。
SYN/ACK报文:
7号报文是服务器的响应。一旦服务器接收到客户端的SYN报文,就读取报文的序列号并且使用此编号作为响应,也就是说它告知客户机,服务器接收到了SYN报文,通过对原SYN报文序列号加一并且作为响应编号来实现,之后客户端就知道服务器能够接收通信。
ACK报文:
8号报文是客户端对服务器发送的确认报文,告诉服务器客户端接收到了SYN/ACK报文,并且与前一步一样客户端也将序列号加一,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
ARP & ICMP:
开启Wireshark抓包。打开Windows控制台窗口,使用ping命令行工具查看与相邻机器的连接状况。
停止抓包之后,Wireshark如下图所示。ARP和ICMP报文相对较难辨认,创建只显示ARP或ICMP的过滤条件。
ARP报文:
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。其功能是:主机将ARP请求广播到网络上的所有主机,并接收返回消息,确定目标IP地址的物理地址,同时将IP地址和硬件地址存入本机ARP缓存中,下次请求时直接查询ARP缓存。
最初从PC发出的ARP请求确定IP地址192.168.1.1的MAC地址,并从相邻系统收到ARP回复。ARP请求之后,会看到ICMP报文。
ICMP报文:
网络控制消息协定(Internet Control Message Protocol,ICMP)用于TCP/IP网络中发送控制消息,提供可能发生在通信环境中的各种问题反馈,通过这些信息,令管理者可以对所发生的问题作出诊断,然后采取适当的措施解决。
PC发送echo请求,收到echo回复如上图所示。ping报文被mark成Type 8,回复报文mark成Type 0。
如果多次ping同一系统,在PC上删除ARP cache,使用如下ARP命令之后,会产生一个新的ARP请求。
C:\> ping 192.168.1.1
... ping output ...
C:\> arp –d *
HTTP协议是目前使用最广泛的一种基础协议,这得益于目前很多应用都基于WEB方式,实现容易,软件开发部署也简单,无需额外的客户端,使用浏览器即可使用。这一过程开始于请求服务器传送网络文件。
从上图可见报文中包括一个GET命令,当HTTP发送初始GET命令之后,TCP继续数据传输过程,接下来的链接过程中HTTP会从服务器请求数据并使用TCP将数据传回客户端。传送数据之前,服务器通过发送HTTP OK消息告知客户端请求有效。如果服务器没有将目标发送给客户端的许可,将会返回403 Forbidden。如果服务器找不到客户端所请求的目标,会返回404。
如果没有更多数据,连接可被终止,类似于TCP三次握手信号的SYN和ACK报文,这里发送的是FIN和ACK报文。当服务器结束传送数据,就发送FIN/ACK给客户端,此报文表示结束连接。接下来客户端返回ACK报文并且对FIN/ACK中的序列号加1。这就从服务器端终止了通信。要结束这一过程客户端必须重新对服务器端发起这一过程。必须在客户端和服务器端都发起并确认FIN/ACK过程。
TCP/IP协议栈
以太网帧示例
IP数据报格式
IP报文示例
UDP帧结构
TCP消息结构
TCP报文示例
IO graphs是一个非常好用的工具。基本的Wireshark IO graph会显示抓包文件中的整体流量情况,通常是以每秒为单位(报文数或字节数)。默认X轴时间间隔是1秒,Y轴是每一时间间隔的报文数。如果想要查看每秒bit数或byte数,点击“Unit”,在“Y Axis”下拉列表中选择想要查看的内容。这是一种基本的应用,对于查看流量中的波峰/波谷很有帮助。要进一步查看,点击图形中的任意点就会看到报文的细节。
为了讲解方便,点击示例报文包,或用自己的wireshark点击Statistics – IO Graphs。这个抓包是HTTP下载遇到报文丢失的情况。
注意:过滤条件为空,此图形显示所有流量。
这个默认条件下的显示在大多数troubleshooting中并不是非常有用。将Y轴改为bits/tick这样就可以看到每秒的流量。从这张图可以看到峰值速率是300kbps左右。如果你看到有些地方流量下降为零,那可能是一个出问题的点。这个问题在图上很好发现,但在看报文列表时可能不那么明显。
每一个图形都可以应用一个过滤条件。这里创建两个不同的graph,一个HTTP一个ICMP。可以看到过滤条件中Graph 1使用“http”Graph 2使用“icmp”。图中可以看到红色ICMP流量中有些间隙,进一步分析。
创建两个图形,一个显示ICMP Echo(Type=8)一个显示ICMP Reply(Type=0)。正常情况下对于每一个echo请求会有一个连续的reply。这里的情况是:
可以看到红色脉冲线(icmp type==0 – ICMP Reply)中间有间隙,而整张图中ICMP请求保持连续。这意味着有些reply没有接收到。这是由于报文丢失导致的reply drop。CLI中看到的ping信息如下:
对于排查网络延时/应用问题有一些过滤条件是非常有用的:
注意:Graph 1是HTTP总体流量,显示形式为packets/tick,时间间隔1秒。Graph 2是TCP丢失报文片段。Graph 3是TCP 重复ACK。Graph 4是TCP重传。
从这张图可以看到:相比于整体HTTP流量,有很多数量的重传以及重复ACK。从这张图中,可以看到这些事件发生的时间点,以及在整体流量中所占的比例。
IO Graphs有六个可用函数:SUM, MIN, AVG, MAX, COUNT, LOAD。
MIN( ), AVG( ), MAX( ):
首先看一下帧之间的最小,平均和最大时间,这对于查看帧/报文之间的延时非常有用。我们可以将这些函数结合“frame.time_delta”过滤条件看清楚帧延时,并使得往返延时更为明显。如果抓包文件中包含不同主机之间的多个会话,而只想知道其中一个pair,可将“frame.time_delta”结合源和目标主机条件如“ip.addr==x.x.x.x && ip.addr==y.y.y.y”。如下图所示:
我们做了以下步骤:
将Y轴设置为“Advanced”,让Caculation域可见。不做这一步就看不到计算选项。 X轴时间间隔1秒,所以每个柱状图代表1秒间隔的计算结果。 过滤出两个特定IP地址的HTTP会话,使用条件:“(ip.addr==192.168.1.4&& ip.addr==128.173.87.169) && http”。 使用3个不同的graph,分别计算Min(), Avg(), Max()。 对每一个计算结果应用条件“frame.time_delta”,将style设置成“FBar”,显示效果最佳。 从上图可见,在第106秒时数据流的MAX frame.delta_time达到0.7秒,这是一个严重延时并且导致了报文丢失。如果想要深入研究,只需要点击图中这一点,就会跳转至相应帧。对应于本例抓包文件中第1003个报文。如果你看见帧之间平均延时相对较低但突然某一点延时很长,可点击这一帧,看看这一时间点究竟发生了什么。
Count( ):
此函数计算时间间隔内事件发生的次数,在查看TCP分析标识符时很有用,例如重传。例图如下:
Sum( ):
该函数统计事件的累加值。有两种常见的用例是看在捕获TCP数据量,以及检查TCP序列号。让我们看看第一个TCP长度的例子。创建两个图,一个使用客户端IP 192.168.1.4为源,另一个使用客户端IP作为一个目的地址。每个图我们将sum()功能结合tcp.len过滤条件。拆分成两个不同的图我们就可以看到在一个单一的方向移动的数据量。
从图表中我们可以看到,发送到客户端的数据量(IP.DST = = 192.168.1.4过滤条件)比来自客户端的数据量要高。在图中红色表示。黑条显示从客户端到服务器的数据,相对数据量很小。这是有道理的,因为客户只是请求文件和收到之后发送确认数据,而服务器发送大文件。很重要的一点是,如果你交换了图的顺序,把客户端的IP作为图1的目标地址,并且客户端IP作为图2的源地址,采用了FBAR的时候可能看不到正确的数据显示。因为图编号越低表示在前台显示,可能会覆盖较高图号。
现在让我们看一下同一个数据包丢失和延迟的TCP序列号。
可以在图中看到若干峰值和下降,表示TCP传输有问题。与正常TCP报文比较:
这张图可以看到TCP序列号相当稳定地增加,表示传输平稳,没有过多重传或丢包。
作为网络管理员,很多时间必然会耗费在修复慢速服务器和其他终端。但用户感到网络运行缓慢并不意味着就是网络问题。 解决网络性能问题,首先从TCP错误恢复功能(TCP重传与重复ACK)和流控功能说起。之后阐述如何发现网络慢速之源。最后,对网络各组成部分上的数据流进行概况分析。这几张内容将会帮助读者识别,诊断,以及排查慢速网络。
接下来的内容,较多是黑白图片了。虽然看起来有点不爽,但还是很值得一看。
TCP的错误恢复功能是定位,诊断及修复网络延时的最佳工具。 延时可以在单程也可以往返方向测量。高延时是网络管理员的头号大敌。本节我们讨论TCP高延时是如何导致序列号和确认号乱序的。
主机报文重传是TCP最基本的错误恢复功能,它的目的是防止报文丢失。
报文丢失的可能因素有很多种,包括应用故障,路由设备过载,或暂时的服务宕机。报文级别速度是很高的,而通常报文丢失是暂时的,因此TCP能够发现和恢复报文丢失显得尤为重要。
决定报文是否有必要重传的主要机制是重传计时器(retransmission timer),它的主要功能是维护重传超时(RTO)值。当报文使用TCP传输时,重传计时器启动,收到ACK时计时器停止。报文发送至接收到ACK的时间称为往返时间(RTT)。对若干次时间取平均值,该值用于确定最终RTO值。在最终RTO值确定之前,确定每一次报文传输是否有丢包发生使用重传计时器,下图说明了TCP重传过程。
当报文发送之后,但接收方尚未发送TCP ACK报文,发送方假设源报文丢失并将其重传。重传之后,RTO值加倍;如果在2倍RTO值到达之前还是没有收到ACK报文,就再次重传。如果仍然没有收到ACK,那么RTO值再次加倍。如此持续下去,每次重传RTO都翻倍,直到收到ACK报文或发送方达到配置的最大重传次数。
最大重传次数取决于发送操作系统的配置值。默认情况下,Windows主机默认重传5次。大多数Linux系统默认最大15次。两种操作系统都可配置。 示例如下图:
TCP重传过程发送的第一个报文如下图所示(图片不很清楚,已经尽力了):
这是一个TCP PSH/ACK报文①,包含648字节数据②,从10.3.30.1发送至10.3.71.7。这是一个典型的数据报文。
在通常情况下,第一个报文发送之后很快会收到TCP ACK报文。然而,在这个case里,第二个是重传报文。可以在Packet list面板里看到。Info栏清楚的标明“TCP Retransmission”,报文以黑色背景红色字体标出。下图是Packet List面板中的重传示例(仍然不清楚,但可参见上图):
也可以在Packet Details和Packet Bytes面板中查看来确定是否是重传报文,如下图所示:
注意此报文与源报文相同(除了IP标识和checksum字段)。要验证这一点,比较两个报文的Packet Bytes①。
在Packet Details面板,注意到重传报文在SEQ/ACK Analysis下面有些额外的信息②。这些信息是由Wireshark提供的而并非报文本身。SEQ/ACK Analysis告诉我们这确实是一个重传报文,RTO值是0.206秒,此时的RTO是基于报文1的时间增量。
检查剩下的报文会得到类似的结果,不同之处只有IP标识和checksum,以及RTO值。要使报文之间的时间间隔形象化,在Packet List面板中查看Time栏,如下图所示。这里可以看到RTO值的翻倍增长关系。
重复ACK是指在接收方收到乱序报文时,所发出的一类TCP报文。TCP使用报文头的序列号和确认号以有效保证数据按照发送的顺序接收和重组。
当TCP连接建立以后,握手过程中交换的一个最重要的信息是初始序列号(ISN)。一旦连接双方设定了ISN之后,接下来发送的报文所包含的序列号增加一个数据载荷值。
假设有个主机ISN是5000,发送500字节报文至接收方。一旦报文接收之后,接收端回复一个ACK号为5500的TCP ACK报文,基于以下公式: Sequence Number In + Bytes of Data Received = Acknowledgment Number Out 按照上述计算结果,返回发送端的确认编号实际上是接收端希望收到的序列号。示例如下图:
数据接收方通过序列号来检查报文丢失。接收方通过追踪接收到的序列号,能够确认序列号是否乱序。当接收方收到一个不正常的序列号,它会假设传输过程中有报文丢失。为了正确重传数据,接收方必须拥有丢失报文,所以它发送包含有丢失报文正确序列号的ACK报文,以便发送方重传此报文。
当重传主机从发送端接收到3个重复ACK时,它会假设此报文确实在传送中丢失,并且立即发送一个快速重传。一旦触发了快速重传,所有正在传输的其他报文都被放入队列中,直到快速重传报文发送为止。过程如下图所示:
承接上文的彩图:
本例中第一个报文如下图:
这是一个TCP ACK报文,从数据接收端(172.31.136.85)发给发送端(195.81.202.68)①,确认前一个报文所发送的数据。 此报文中的确认编号是1310973186②,应当是下一个接收报文的序列号,如下图所示:
不幸的是接收端的序列号是1310984130①,并不是所期望的值。这意味着报文在传送中丢失。接收端注意到报文乱序,并且在第三个报文中发送重复ACK,如下图所示:
可以通过以下两种方式之一来确认这是一个重复ACK: 在Packet Detaisl面板中的Info栏。报文呈现黑色背景红色字体。 SEQ/ACK Analysis下的Packet Deatails面板。扩展这一栏会发现报文显示为duplicate ACK。接下来几个报文重复此过程。如下图所示:
此文件中的第四个报文是发送端所发出具有错误序列号①的另一个数据块。因此,接收端发送第二个重复ACK②。接收端又收到一个乱序报文③。从而触发了第三以及最后一个重复ACK④.
一旦发送方接收到接收方所发来的第三个重复ACK,它就会暂停所有传输报文并且重传丢失报文,下图显示了快速重传过程:
重传报文同样可以通过Packet List面板的Info栏观察到。报文呈现黑色背景红色字体。这个报文的SEQ/ACK Analysis截面告诉我们这可能是一个快速重传帧。(标识报文为快速重传的信息不是报文本身所包含的内容,而是Wireshark的功能)。最后一个报文是接收到快速重传的ACK。
TCP通过滑动窗口机制检测丢包,并在丢包发生时调整数据传输速率。滑动窗口机制利用数据接收端的接收窗口来控制数据流。 接收窗口值由数据接收端指定,以字节数形式存储于TCP报文头,并告知传输设备有多少数据将会存储在TCP缓冲区。缓冲区就是数据暂时放置的地方,直至传递至应用层协议等待处理。因此,发送端每次只能发送Window Size字段指定的数据量。为了使发送端继续传送数据,接收端必须发送确认信息:之前的数据接收到了。同时必须对占用缓冲区的数据进行处理以释放缓存空间。下图显示了接收窗口是如何工作的:
上图中,客户端向服务器发送数据,服务器接收窗口是5000字节。客户端发送了2500字节,服务器缓冲区还剩2500字节,之后又发送了2000字节,从而缓冲区只剩500字节。服务器发送确认信息。对缓存中数据进行处理并清空缓存。此过程重复进行,客户端又发送3000字节和1000字节,服务器缓存减少至1000字节,客户端再次确认数据并处理缓存中内容。
当TCP堆栈接收到数据的时候,生成一个确认信息并以回复的方式发送,但是放置在接收端缓存中的数据并不总是立即被处理。当服务器忙于处理从多个客户端接收的报文,服务器很有可能因为清理缓存而变得缓慢,无法腾出空间接收新的数据,如果没有流控,则可能会造成丢包和数据损坏。好在,接收窗口所设定的速率无法使服务器正常处理数据时,能够调整接收窗口大小。通过减小返回给发送端的ACK报文的TCP头窗口大小值来实现。如下图所示:
上图中,服务器初始窗口大小为5000字节。客户端发送2000字节,之后又发送了2000字节,缓冲区中只有1000字节可用。服务器意识到缓冲区正在快速填满,它知道如果数据继续以此速率传输,很快会有报文丢失。为了防止报文丢失,服务器发送确认信息给客户端,更新窗口大小为1000字节。结果,客户端减少数据发送,服务器以可以接受的速率处理缓存内容,即保持数据流以稳定的速率传输。
调整窗口大小在两个方向都是可行的。当服务器能够更加快速的处理报文时,它会发送一个较大窗口的ACK报文。
某些情况下,服务器无法再处理从客户端发送的数据。可能是由于内存不足,处理能力不够,或其他原因。这可能会造成数据被丢弃以及传输暂停,但接收窗口能够帮助减小负面影响。
当上述情况发生时,服务器会发送窗口为0的报文。当客户端接收到此报文时,它会暂停所有数据传输,但会保持与服务器的连接以传输探测(keep-alive)报文。探测报文在客户端以稳定间隙发送,以查看服务器接收窗口状态。一旦服务器能够再次处理数据,将会返回非零值窗口大小,传输会恢复。下图示例了零窗口通知过程。
服务器初始接收数据窗口为5000字节大小。从客户端接收4000字节数据之后,服务器负载变得非常繁重,无法继续处理客户端任何数据。服务器于是发送窗口大小值为0的报文。客户端暂停数据传输并发送一个探测报文。探测报文之后,服务器回复以告知客户端现在可以接收数据的报文,以及窗口大小为1000字节。客户端恢复传送数据。
本例中,开始从192.168.0.20发送至192.168.0.30。我们关心的是窗口大小字段,可以从Packet List面板的Info栏以及Packet Details的TCP报文头看到。前三个报文后,可看到该值立刻减小,如下图所示:
窗口大小值从第一个报文的8760字节变成第二个报文的5840字节到第三个报文的2920字节①。窗口大小值的减小是主机延时的典型标志。在时间栏注意到这一过程发生的非常迅速②。当窗口大小迅速减小的时候,通常就有可能下降为零。这就是第四个报文所发生的,如下图所示:
第四个报文从192.168.0.20发送至192.168.0.30,目的是告诉192.168.0.30它不再接收任何数据。0值见于TCP报文头①,Wireshark的Packet List面板Info栏,以及TCP报文头的SEQ/ACK Analysis字段②也告诉我们这是一个0窗口报文。
一旦发送了零窗口报文,192.168.0.30的设备不会再发送任何数据,直到收到从192.168.0.20的窗口更新,告知窗口大小已经增加了。本例中导致零窗口的问题是暂时的,所以在下一个报文中发送了窗口更新信息,如下图所示。
本例中,窗口大小增加到一个非常健康的数值64,240字节①。Wireshark再次在SEQ/ACK Analysis告诉我们这是一个窗口更新。
一旦收到更新报文,192.168.0.30的主机就再次开始发送数据,在报文6和报文7中。这一过程发生很快。如果它持续时间再长一点,就可能会导致网络的潜在中断,引起数据传输减慢或失败。
下一个关于滑动窗口的例子,第一个报文是正常HTTP,从195.81.202.68至172.31.136.85。此报文之后立刻跟随一个从172.31.136.85发送的零窗口报文,如下图所示:
这与上一个例子中的零窗口报文十分类似,但结果显著不同,172.31.136.85主机不是发送一个窗口更新并回复通讯,而是一个探测报文,如下图所示:
此报文被Wireshark标注为探测报文①。时间栏告诉我们这一报文发生于最后一个接收到的报文3.4秒之后。这一过程持续若干次,一端发送零窗口报文另一端发送探测报文,如下图所示:
探测报文发送间隙为3.4,6.8,13.5秒。这一过程可能会持续相当长一段时间,取决于通讯设备的操作系统。该情况下,把时间栏的值加起来,通讯暂停了25秒。
重传报文
重传的发生是由于客户端检测到服务器没有接收到它所发送的数据。因此,取决于你所分析的是通讯的哪一端,有可能是看不见重传的。如果从服务器端抓取数据,并且它确实没有接收到客户端所发送的和重传报文,可能会一无所获因为无法看见重传报文。如果怀疑并不是服务器端导致的报文丢失,可以考虑在客户端尝试抓取报文,以查看实际是否有重传发生。
重复ACK
可以将重复ACK看作重传的“所谓相反面”,因为它是在服务器检测到客户端发送报文丢失的时候产生的。大多数情况下,在通讯两端抓取流量时都可以看到重复ACK。需记住当接收报文乱序时会触发重复ACK。例如,如果服务器之接收到发送的第一个和第三个报文,就会导致发送重复ACK引起客户端对第二个报文的快速重传,因为你已经收到了第一个和第三个报文,因此不管导致第二个报文丢弃的原因是什么,都很有可能是暂时的,因此大多数情况下重复ACK都会成功发送和接收。当然,这种情形并不一定永远会发生,因此当你怀疑在服务器端丢失报文而又看不到任何重复ACK,考虑从通讯的客户端抓取报文。
零窗口和探测报文
滑动窗口直接与服务器无法接收和处理报文有关,任何窗口大小的缩小以及零值都是服务器问题的直接结果。所以如果你在哪里看到这两者之一发生,就应该在那里深入研究。通常应当在网络通讯两端一直主机窗口更新报文。
在某些情况下,丢包可能并不是造成延时的原因。你可能会发现尽管两台主机之间通讯速度很慢,但这种慢速并没有伴随着TCP重传或是重复ACK的征兆。在这种情况下,需要使用另一种方式来定位高延时点。
查找高延时点最有效的方法之一是检查最初的握手信号以及跟随其后的几个报文。例如,一个简单的客户端与网络服务器的连接,客户端尝试通过浏览器访问网络服务器的站点。我们只关心这一通信序列的前六个报文,包括TCP握手过程,首次HTTP GET请求,对此GET请求的确认,以及从服务器发至客户端的第一个数据报文。
在讨论高延时状况之前,找一个正常的通讯作为参照。在第二节已经介绍过TCP握手过程以及HTTP通讯,这里不再赘述。在下面这张图里,我们关心的部分只有Time列:
这一通讯序列是非常快速的,整个过程耗时不到0.1秒。 接下来几个抓包文件包含同样的traffic模式,但是在报文时序上有所不同。
让我们看看下面这个报文。注意到所有报文都是相同的,除了报文2和5的时间延时较长:
逐一分析这六个报文,立刻就会看到第一次延时。客户端(172.16.16.128)发送首次SYN报文以开始TCP握手,在服务器(74.125.95.104)返回SYN/ACK之前,有0.87秒的延时。这是线路延时的第一个信号,这是由客户端和服务器之间的设备引起的。 我们判断这是线路延时的依据是所传送的报文类型特征。当服务器接收到一个SYN报文,只需花费很少的处理过程就可发送回复,因为这一工作负载并不包含任何传输层之上的处理。即使服务器工作负载非常繁重,它通常也会快速地以SYN/ACK来回复SYN报文。这就排除了服务器是高延时的潜在原因。 客户端也被排除的原因在于,它除了接收SYN/ACK报文之外,没有进行任何处理。 这一抓包的前两个报文帮我们排除了客户端和服务器,并指出了潜在原因。
继续分析,我们发现结束三步握手信号的ACK报文快速出现,客户端发送的HTTP GET请求也是如此。产生这两个报文的所有处理在本地客户端接收到SYN/ACK之后进行,因此在客户端没有繁重的负载需要处理的情况下,这两个报文预计会很快传送。
到了报文5,我们看到另一个延时高得离谱的报文。出现在最初的HTTP GET请求发送过后,从服务器返回的ACK报文花费了1.15秒才收到。接收到HTTP GET请求之后,服务器在开始发送数据之前首先发送了一个TCP ACK,同样只需占用服务器很少的处理。这是另一个线路延时的信号。
不管何时你经历着线路延时,你几乎总是会看到:在最初的握手信号期间的SYN/ACK报文,以及整个通讯过程的ACK报文中,存在着高延时。即使这一信息并没有告诉你网络上延时的确切原因,至少让你明白客户端和服务器都不是延时点所在,因此延时发生在两者之间的设备。这时,你应当开始检查受影响主机之间的各种防火墙,路由器,以及代理,以定位罪魁祸首。
下一个延时场景的抓包如下图所示:
这一抓包开始时很正常,TCP握手非常迅速,没有任何延时的迹象。正常状态持续至第四个报文:握手信号结束之后接收到一个HTTP GET请求。这个报文距离前一个接收到的报文有1.34秒的延时。
要确认网络的延时点,需要检查第3和第4个报文之间发生了什么。报文3是客户端发送到服务器的TCP握手信号中的最后一个ACK,报文4是从客户端发送至服务器的GET请求。这两个报文的共同之处在于都是由客户端发送,并且独立于服务器。由于所有这些操作都集中在客户端上,GET请求应当在发送了ACK之后快速传送。 不幸的是对于终端用户,从ACK到GET的传送并没有快速发生。GET报文的创建与传输取决于应用层的处理,这一过程中的延时意味着客户端无法及时的执行这一功能。这表示客户端最终为通讯中的高延时负责。
最后一个延时场景的抓包如下图所示:
在这一抓包中,两个主机之间的TCP握手过程完成得干脆利落,因此开始时并无问题。接下来几个报文也很顺利,首个GET请求及回复ACK报文也在快速交付。直到最后一个报文,我们看到了高延时的信号。
第六个报文是服务器响应客户端GET请求的第一个HTTP数据报文,但是在服务器发送GET请求的TCP ACK 0.98秒之后才到达。报文5和6的传送过程与我们在前一个场景所见ACK和GTE请求的传送类似。但是,在这一情况下,服务器是我们关注的焦点。
报文5是服务器对从客户端接收GET请求的回应。只要该报文被发送,服务器就应当立即发送数据。这一读取,封装,传送的过程是由HTTP协议完成的,由于这是应用层协议,需要服务器参与处理过程。这一报文的延迟接收表明服务器无法在合理的时间内处理数据,最终指向服务器是延时点。
通过六个报文,我们能够定位服务器与客户端之间的网络高延时点。这些场景可能看起来有点复杂,但是下图能使你的定位延时过程变得简单快捷。这一原则几乎能应用于任何基于TCP的通讯。
Wireshark一个强大的功能在于它的统计工具。使用Wireshark的时候,我们有各种类型的工具可供选择,从简单的如显示终端节点和会话到复杂的如Flow和IO图表。本文将介绍基本网络统计工具。包括:捕捉文件摘要(Summary), 捕捉包的层次结构(Protocol Hirarchy), 会话(Conversations), 终端节点(Endpoints), HTTP。
从statistics菜单,选择Summary:
如下图的截屏所示,你会看到:
在窗口的较低部分是Display窗口,展示抓包文件统计信息的摘要,包括:
何时使用:
这一菜单简单收集所有抓包数据,在定义了过滤条件的时候,将呈现过滤后的数据。当想要知道每秒的平均报文数或是字节数时,可以使用此工具。
这一部分阐述如何确知网络运行数据。从statistics菜单,选择Protocol Hierarchy。
这个窗口现实的是捕捉文件包含的所有协议的树状分支。如下图所示:
Protocol Hierarchy窗口有如下字段:
小贴士:
包通常会包含许多协议,有很多协议会在每个包中被统计。End Packets,End Bytes,End Mbit/s列是该层在抓包中作为最后一层协议的统计数据(也就是说,协议处于报文的顶层,并且没有更高层信息了)。例如,没有载荷的TCP报文(例如,SYN报文),这一类没有负载任何上层信息的报文。这就是为什么在Ethernet层,IPv4层和UDP层报文计数为0,因为没有接收到以这些协议作为最后一层的帧。
使用要点:
6.要查看IP地址对应名称,可以选择Name resolution复选框。要查看IP名称解析,进入View | Name Resolution | Enable for Network layer进行激活。
使用要点:
网络会话是两个指定终端之间的数据流。例如,IP会话是两个IP地址之间的所有数据流,TCP会话包含了所有TCP连接。 通过Conversations列表,能看出很多网络问题。
以太网会话统计
在Ethernet conversations statistics中,查找以下问题:
IP会话统计
在IP conversations statistics中,查找以下问题:
本例中的扫描模式,一个IP地址,192.168.110.58,发送ICMP报文至192.170.3.44, 192.170.3.45, 192.170.3.46, 192.170.3.47,等等(上图仅显示扫描的很小一部分)。这种情况下我们有一个蠕虫病毒感染了网络上的所有PC,在它感染PC的时候,它就开始产生ICMP请求并将它们发送至网络。这些窄带连接(例如:WAN连接)可以很容易地被封锁。
TCP/UDP会话统计
Endpoints:
使用要点:
这一工具列出了Wireshark发现的所有endpoints上的统计信息。可以是以下任意一种情况:
以下是一个网络中心的抓包示例,一个内部网络有四个HP服务器和一个Cisco路由器,MAC地址的第一部分已经解析了厂商名称:
当我们查看IPv4:191下的endpoints,我们看到有很多来自192.168.10.0, 192.168.30.0,以及其他网络地址。
从statistics菜单,选择HTTP,将会出现以下窗口:
在HTTP子菜单中,可以看到以下信息:
- Packet Counter:
每一个网站的报文数量。帮助识别有多少响应和请求。
- Requests:
各网站的请求分布。
- Load Distribution:
各网站的负载分布。
按照以下操作步骤查看Packet Counter统计信息:
1. 进入Statistics | HTTP | Packet Counter。
2. 显示以下过滤窗口:
3. 此窗口中,可设置过滤条件以查看符合过滤条件的统计信息。如果想要查看整个抓包文件的统计信息,留白不填。这就会显示IP层之上的统计信息,也就是所有HTTP报文。
4. 点击Create Stat按钮,会看到以下窗口:
如果要查看某一特定节点的HTTP统计信息,可以通过display filter的方式配置过滤条件。
按照以下操作步骤查看HTTP Requests统计信息:
1. 进入Statistics | HTTP | Requests,出现以下窗口:
2. 选择所需过滤条件。对于所有数据,留白。
3. 点击Create Stat按钮,会出现以下窗口:
4. 要获得指定HTTP主机的统计信息,设置过滤条件http.host contains <host_name> 或 http.host==<host_name>。
5. 例如,通过设置过滤条件http.host contains ndi-com.com,可以获得站点 www.ndi-com.com的统计信息,如下图所示:
![image020](https://cloud.githubusercontent.com/assets/207689/4732437/e38a3228-59bb-11e4-9b3d-df392992e369.jpg)
6. 结果如下图所示:
按照以下操作步骤查看Load Distribution统计信息:
1. 进入Statistics | HTTP | Load Distribution。
2. 出现以下窗口:
3. 选择所需过滤条件。对于所有数据,留白。
4. 点击Create Stat按钮,会出现以下窗口:
使用要点:
当我们打开一个网页,通常会向若干个URL发送请求。本例中,我们打开的其中一个网页是www.cnn.com,并将我们导向edition.cnn.com。我们发送了若干个请求:到root URL,到breaking_news URL,以及主页上两个其他位置。
应用抓包过滤,选择Capture | Options,扩展窗口查看到Capture Filter栏。双击选定的接口,如下图所示,弹出Edit Interface Settints窗口。
下图显示了Edit Interface Settings窗口,这里可以设置抓包过滤条件。如果你确知抓包过滤条件的语法,直接在Capture Filter区域输入。在输入错误时,Wireshark通过红色背景区域表明无法处理过滤条件。最有可能的情况是,过滤条件中含有输入错误,或是使用了display filter的语法。
点击Capture Filter按钮查看并选择已保存的抓包过滤条件。
如果你的抓包环境下有很多主机正在通讯,可以考虑使用所观察主机的IP地址来进行过滤。以下为IP地址抓包过滤示例:
当你需要抓取来自/发到一组地址的数据流,可以采用CIDR(无类别域间路由,Classless Interdomain Routing)格式或使用mask参数。
方括号中第一个数字表示从协议头开始的偏移量,第二个数字表示需要观察多少位。
只需侦听广播或多播数据流,就可以掌握网络上主机的许多信息。
小贴士:
Wireshark包含了一些默认的抓包过滤条件。点击主工具栏的Edit Capture Filters,跳转到已保存抓包过滤列表。你会发现一些常见抓包过滤的示例。
当你需要抓取发到/来自某一主机的IPv4或IPv6数据流,可创建基于主机MAC地址的抓包过滤条件。 应用MAC地址时,需确保与目标主机处于同一网段。
你可能需要查看基于一个或几个应用的数据流。抓包过滤器语法无法识别应用名,因此需要根据端口号来定义应用。通过目标应用的TCP或UDP端口号,将不相关的报文过滤掉。
当你需要抓取多个不连续端口号的数据流,将它们通过逻辑符号连接起来,如下图所示:
尽量避免使用抓包过滤。即便多看几个报文,也比漏看一个报文要好。当你抓取了大量报文的时候,用显示过滤(过滤选项也更多)来重点查看某一数据流。
小贴士: 如果你需要查看TCP帧中的某一ASCII字符串,用Wireshark String-Matching Capture Filter Generator(http://www.wireshark.org/tools/string-cf.html)。例如,想要抓取HTTP GET报文,输入GET并将TCP偏移量设置为0。
掌握显示过滤器对于网络分析者来说是一项必备的技能。这是一项大海捞针的技巧。学会构建,编辑,保存关键的显示过滤器能够节省数小时的时间。
与捕捉过滤器使用的BPF语法不同,显示过滤器使用的是Wireshark特定的格式。除了某些特例之外,Wireshark显示过滤器和捕捉过滤器有很大的区别。
最简单的显示过滤器可基于协议,应用,域名,或字符,对大小写敏感。绝大多数简单的显示过滤器由小写字母组成。
很多显示过滤器都是基于字段名(例如http.host)。要了解字段名,在Packet list面板选中字段查看Status条,如下图所示。
本例中,我们在Packet Display面板中选中第10帧,然后在Packet Details面板中展开HTTP报文头。之后在报文的HTTP段点击Request Method行,状态条表明这一字段称为http.request.method。
我们在显示过滤器区域输入http.request.method以显示所有包含这一字段的报文。如下图所示,注意到Status条表明此抓包文件包含2011个报文只有101个报文符合过滤条件。
这是一个很好用的过滤器,以确定HTTP客户端请求了哪些内容。网络服务器不发送HTTP request method,它们发送HTTP响应代码。
当你在过滤器区域输入http.request.method的时候,Wireshark打开一个窗口让你遍历过滤器选项。当你输入http.(包括点号),你会看到所有可能的以此为开头的显示过滤条件列表。继续输入http.request. ,会看到以这一短语为开头的过滤条件,如下图所示:
可以使用这一自动完成功能查看所有可用的过滤条件。例如,输入tcp. ,Wireshark会列出所有可用的TCP过滤条件。如果输入tcp.analysis. ,Wireshark会列出所有处理TCP问题与性能的TCP analysis过滤条件,如下图:
通过扩展过滤条件可查找某一域值,Wireshark针对此功能支持数字比较运算符。
或gt 例如:frame.time_relative > 1 显示距前一个报文到达时间相差1秒的报文
=或ge 例如:dns.count.answers >= 10 显示包含10个以上answer的DNS响应报文
对于基于TCP应用的过滤条件采用比较运算符。例如,如果想看端口80上面的HTTP数据流,使用HTTP.port==80。
小贴士: 运算符两边不用留空格。ip.src == 10.2.2.2与ip.src==10.2.2.2的效果是相同的。
当你实在不知道该过滤些什么的时候,使用显示过滤器工具栏的Expression按钮。在Filter Expression窗口,输入感兴趣的应用或协议名,跳转到Field Name列表中相应条目。Relation选项用来添加一个比较运算符,窗口右端是预先定义的值。点击Apply按钮完成。
Wireshark提供15个缺省显示过滤器供创建新的显示过滤器时参考。点击Filter按钮或点击Display Filter按钮打开显示过滤器窗口,如下图所示:
下图显示了缺省过滤器列表,选中之后点击OK。
小心使用缺省过滤器。以太网和IP主机过滤器可能与实际网络不符。使用之前必须编辑或作为创建参考。
小贴士:
显示过滤器保存在一个名为dfilters的文件中,可以使用任何文本编辑器来进行编辑。要找到你的dfilters文件,首先在Status条的右端查找当前profile名。如果这一区域表明你在默认profile,选择Help\About Wireshark\Folders并双击Personal Configuration文件夹链接,dfilters文件就在这个目录里。
掌握显示过滤器对于网络分析者来说是一项必备的技能。这是一项大海捞针的技巧。学会构建,编辑,保存关键的显示过滤器能够节省数小时的时间。
与捕捉过滤器使用的BPF语法不同,显示过滤器使用的是Wireshark特定的格式。除了某些特例之外,Wireshark显示过滤器和捕捉过滤器有很大的区别。
在排查网页浏览器会话或检查网速过慢问题时,对浏览器会话进行过滤就显得尤为重要。过滤HTTP数据流有两种方式:通过协议:http 或者 tcp.port==xx(xx表示所使用的HTTP端口)。第二种过滤方法更加有效。让我们通过分别对网页浏览会话应用两个过滤条件来比较一下。
基于TCP端口号的应用过滤:
本例中的抓包文件包含与网站www.wireshark.org的链接以及请求下载Wireshark的请求。我们使用tcp.port==80的显示过滤器并且发现,确实,所有报文都符合条件,如下图所示。很好这就是我们想要的结果。
我们仔细看报文20的Protocol列,Wireshark并没有在报文中看到任何HTTP命令或回复,因此HTTP协议分析器没有被应用于此报文。它只是一个TCP报文(TCP ACK, FIN, RST,以及三路TCP握手信号都列成TCP)。
如果你想要查看TCP连接建立,维护以及关闭报文,就应该使用上述过滤条件(并且你会一直看到这些TCP报文)。
谨慎使用基于TCP的应用名过滤:
现在来看一下对数据流应用http过滤条件的情况。下图中,你会看到Wireshark显示了13,353个报文。这些是Protocol列中包含HTTP的报文。
这是整个网站浏览会话的一部分,使用HTTP过滤条件我们无法检测出TCP错误,对于应用永远是使用端口号过滤器优于TCP。
小贴士:
不幸的是,Wireshark对于HTTP数据流的缺省过滤是http。可以考虑将缺省对HTTP数据流的过滤改为基于端口号。
对于IPv4数据流,我们使用字段名ip.src,ip.dst,ip.addr;对于IPv6数据流,使用ipv6.src,ipv6.dst,ipv6.host以及ipv6.addr。注意当你在Packet Details面板中点击IP地址时,将会看到它们被称为:ip.src,ip.dst, ipv6.src或ipv6.dst。字段名ip.host和ipv6.host,ip.addr以及ipv6.addr不在报文里。
ip.host和ipv6.host 过滤条件在IPv4/IPv6源和目的地址字段查找解析为指定主机名的IPv4或IPv6地址。ip.addr==[address]和ipv6.addr==[address]过滤条件在IPv4/IPv6源和目的地址字段查找指定IPv4/IPv6地址。 · 例如:ip.addr==10.3.1.1 显示在IP源地址字段或IP目的地址字段包含10.3.1.1的帧。 · 例如:!ip.addr==10.3.1.1 显示除了在IP源地址字段或IP目的地址字段包含10.3.1.1以外的帧。 · 例如:ipv6.addr==2406:da00:ff00::6b16:f02d 显示以2406:da00:ff00::6b16:f02d为源地址或目的地址的帧。 · 例如:ip.src==10.3.1.1 显示所有来自10.3.1.1的数据流。 · 例如:ip.dst==10.3.1.1 显示所有发往10.3.1.1的数据流 · 例如:ip.host==www.wireshark.org 显示所有解析为www.wireshark.org的IP地址。
可以使用>或<比较运算符或逻辑运算符&&查找某一地址范围内的报文。 · 例如:ip.addr>10.3.0.1&&ip.addr<10.3.0.5 显示来自或发往10.3.0.2,10.3.0.3,10.3.0.4的数据流。 · 例如:(ip.addr>=10.3.0.1&&ip.addr<=10.3.0.6)&&!ip.addr==10.3.0.3 显示来自或发往10.3.0.1,10.3.0.2,10.3.0.4,10.3.0.5,10.3.0.6的数据流,10.3.0.3排除在外。 · ipv6.addr>=fe80::&&ipv6.addr<fec0:: 显示IPv6地址从0xfe80到0xfec0开头的数据流。
可以通过ip.addr字段名定义一个子网。这种格式使用IP地址后跟斜杠以及一个后缀,表明IP地址中定义的网络部分的比特数。 · 例如:ip.addr==10.3.0.0/16 显示在IP源地址或目的地址字段以10.3开头的数据流。 · 例如:ip.addr==10.3.0.0/16 && !ip.addr==10.3.1.1 显示除了10.3.1.1以外,在IP源地址或目的地址字段以10.3开头的数据流。 · 例如:!ip.addr==10.3.0.0/16 && !ip.addr==10.2.0.0/16 显示所有数据流,除了在IP源地址或目的地址字段以10.3和10.2开头的数据流.
如下图所示:在某一帧的Packet Details面板,扩展HTTP部分,右键Request URI一行,选择Apply as Filter | Selected。
Wireshark会创建合适的显示过滤条件(http.request.rui==”/”)并应用于抓包文件。之后过滤得到2个报文,显示用户从两个不同的IP地址访问主页内容,如下图所示。
如果你想排除这类HTTP请求,只要在过滤条件前加!或not。你可以通过右键GET请求并选择Apply as Filter | Not Selected。 not http.request.uri==”/”
如果你感兴趣的是其余HTTP GET请求,可对上述过滤条件扩展:定位在一个HTTP GET请求报文,扩展HTTP部分,右键GET并选择Apply as Filter,这一次选择and Selected选项。之后,显示过滤器显示如下: (not http.request.uri==”/”)&&(http.request.method==“GET”)。 现在可以看到除了default page request(/)之外的所有HTTP GET请求。
当你想要观察客户端应用于服务器进程之间的通讯,你需要查找的是一个“会话“。会话是基于客户端应用和服务器进程的IP地址和端口号。通常抓包文件中会包含数百个会话,了解如何快速定位及过滤无疑是很有帮助的。
以下两种常用方式可从抓包文件中提取单一TCP或UDP会话: · 通过在Packet List面板右键一个TCP或UDP报文并选择Conversation Filter | [TCP|UDP]. · 通过在Packet List面板右键一个TCP或UDP报文并选择Follow [TCP|UDP] Stream。
通过在Packet List面板右键一个TCP或UDP报文并选择Conversation Filter | TCP,如下图所示:
Wireshark对数据流创建并应用以下过滤条件: (ip.addr eq 24.6.173.220 and ip.addr eq 184.84.222.48) and (tcp.port eq 19953 and tcp.port eq 80)。 同样的方法可应用于基于IP地址,以太网地址,UDP地址/端口号结合的会话。
要查看应用命令以及会话中的交换数据,通过在Packet List面板右键一个TCP或UDP报文并选择Follow [TCP|UDP] Stream,如下图所示。如果选择Follow UDP Stream,显示过滤条件会基于IP地址和端口号。如果选择Follow TCP Stream, 显示过滤条件会基于TCP Stream Index number。
错误:ip.addr != 10.2.2.2 显示在IP源地址或IP目的地址不包含10.2.2.2的报文。只要在源或目的IP地址不为10.2.2.2,报文就会被显示出来。这时隐含的或会导致实际上并未过滤任何报文。 正确:!ip.addr == 10.2.2.2 显示IP源地址和IP目的地址都不包含10.2.2.2的报文。
错误:!tcp.flags.syn==1 显示所有不含TCP SYN bit设置为1的报文。其他协议报文,必须UDP和ARP报文也符合这一过滤条件,因为它们的TCP SYN bit没有设置为1。 正确:tcp.flags.syn!=1 只显示包含SYN设置为0的TCP报文。
小贴士: 当你知道只有一个字段符合你的过滤字段名的时候,不要害怕使用!=运算符。有时,这是最好用的过滤运算符。
先给你点个赞!
dafang: 原文在这里,重新边读边整理成了markdown,好文值得花时间阅读并整理
Wireshark基本用法
按照国际惯例,从最基本的说起。
抓取报文:
下载和安装好Wireshark之后,启动Wireshark并且在接口列表中选择接口名,然后开始在此接口上抓包。例如,如果想要在无线网络上抓取流量,点击无线接口。点击Capture Options可以配置高级属性,但现在无此必要。
点击接口名称之后,就可以看到实时接收的报文。Wireshark会捕捉系统发送和接收的每一个报文。如果抓取的接口是无线并且选项选取的是混合模式,那么也会看到网络上其他报文。
上端面板每一行对应一个网络报文,默认显示报文接收时间(相对开始抓取的时间点),源和目标IP地址,使用协议和报文相关信息。点击某一行可以在下面两个窗口看到更多信息。“+”图标显示报文里面每一层的详细信息。底端窗口同时以十六进制和ASCII码的方式列出报文内容。
需要停止抓取报文的时候,点击左上角的停止按键,如下:
彩彩标识:
进行到这里已经看到报文以绿色,蓝色,黑色显示出来。Wireshark通过颜色让各种流量的报文一目了然。比如默认绿色是TCP报文,深蓝色是DNS,浅蓝是UDP,黑色标识出有问题的TCP报文——比如乱序报文。
报文样本:
比如说你在家安装了Wireshark,但家用LAN环境下没有感兴趣的报文可供观察,那么可以去Wireshark wiki下载报文样本文件。打开一个抓取文件相当简单,在主界面上点击Open并浏览文件即可。也可以在Wireshark里保存自己的抓包文件并稍后打开。
过滤报文:
如果正在尝试分析问题,比如打电话的时候某一程序发送的报文,可以关闭所有其他使用网络的应用来减少流量。但还是可能有大批报文需要筛选,这时要用到Wireshark过滤器。 最基本的方式就是在窗口顶端过滤栏输入并点击Apply(或按下回车)。例如,输入“dns”就会只看到DNS报文。输入的时候,Wireshark会帮助自动完成过滤条件。
也可以点击Analyze菜单并选择Display Filters来创建新的过滤条件。
另一件很有趣的事情是你可以右键报文并选择Follow TCP Stream。
你会看到在服务器和目标端之间的全部会话。
关闭窗口之后,你会发现过滤条件自动被引用了——Wireshark显示构成会话的报文。
检查报文:
选中一个报文之后,就可以深入挖掘它的内容了。
也可以在这里创建过滤条件——只需右键细节并使用Apply as Filter子菜单,就可以根据此细节创建过滤条件。
Wireshark是一个非常之强大的工具,第一节只介绍它的最基本用法。网络专家用它来debug网络协议实现细节,检查安全问题,网络协议内部构件等等。