Wireshark应用实验
- 数据链路层
- 网络层
- 传输层
- TCP 和 UDP 段结构
- 分析 TCP 建立和释放连接
- 应用层
数据链路层
- 熟悉 Ethernet 帧结构
其中:
ff ff ff ff ff ff: 接受计算机的MAC地址(目的MAC地址)
38 de ad 0f 28 7d: 发送计算机的MAC地址(源MAC地址)
0800: 使用IPv4协议传输 - 了解子网内/外通信时的 MAC 地址
我的IP 10.60.220.2
① ping 你旁边的计算机(10.60.163.120),同时用 Wireshark 抓这些包,记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址是多少?这个 MAC 地址是谁的?
可以看到,ping其他计算机无响应,推测是由于防火墙的保护作用,但是依然可以抓到我们发送的包,其目的MAC地址:00 74 9c 9f 40 13
源MAC地址:00 e0 4c 36 d2 3e
随后,我将两台计算机连接到同一局域网,这时我的IP地址为 192.168.43.154,旁机IP地址为 192.168.43.95,再次ping 旁机。
依然无法ping到,我们关闭旁机的防火墙,再次ping。
成功,进行抓包。
发出帧的目的 MAC 地址: 36 eb 43 97 e2 82
返回帧的源 MAC 地址: 36 eb 43 97 e2 82
② 然后 ping qige.io ,同时用 Wireshark 抓这些包。
同时我们用nslookup命令查看一下qige.io的IP地址。这里抓到的包地址为:104.18.40.82
发出帧的目的 MAC 地址: 00 74 9c 9f 40 13
返回帧的源 MAC 地址: 00 74 9c 9f 40 13
③ 再次 ping www.baidu.com ,同时用 Wireshark 抓这些包。
用同样的方法得到www.baidu.com的IP地址。这里抓到的包地址为:14.215.177.38
发出帧的目的 MAC 地址: 00 74 9c 9f 40 13
返回帧的源 MAC 地址: 00 74 9c 9f 40 13
结论:
可以看到,在访问www.baidu.com和qige.io时,目的地址是一样的,经过查询,该MAC地址为网关的MAC地址。而在访问同一子网下的计算机时,其目的地址就是该计算机的MAC地址。原因:
MAC地址工作于局域网,局域网之间的互连一般通过现有的公用网或专用线路,需要进行网间协议转换。ARP代理访问非子网计算机时是通过路由器转接的,MAC地址是接入路由器端口的地址,再通过路由器发给相应计算机。所以访问非本子网的计算机时,目的 MAC 是网关的。
- 掌握 ARP 解析过程
① 为防止干扰,先使用 arp -d * 命令清空 arp 缓存。
② ping 你旁边的计算机(10.60.163.130),同时用 Wireshark 抓这些包,查看 ARP 请求的格式以及请求的内容,注意观察该请求的目的 MAC 地址是什么。再查看一下该请求的回应,注意观察该回应的源 MAC 和目的 MAC 地址是什么。
可以看到,ARP请求内容为“Who has 10.60.163.130? Tell 10.60.220.2” 这是在寻找要ping的地址,而这条请求的目的地址为ff ff ff ff ff ff,即广播地址。再来看看回应的包。
源 MAC :ea 9f 67 6b ca 58 (即要ping的那个主机的地址,它在回应我们的提问“10.60.163.130 is at ea 9f 67 6b ca 58”)
目的 MAC 地址:00 e0 4c 36 d2 3e (即我主机的地址)
…
小插曲:
由上图可以看到,对我们做出回应的有两条消息,分别给出了不同的地址。而只有第二个回复的消息源(也就是上文提到的地址),在回复了我们之后又发出了询问,寻找我们的位置,因此我把它视作真正的目的源,那第一个对我们做出回复的地址又是什么呢?暂时不知道答案。
…
③ 再次使用 arp -d * 命令清空 arp 缓存。
④ 然后 ping qige.io (104.18.40.82),同时用 Wireshark 抓这些包。查看这次 ARP 请求的是什么,注意观察该请求是谁在回应。
请求的目的地址:ff ff ff ff ff ff
应答的源地址:00 74 9c 9f 40 13
此时我们看到,在ping qige.io时,依然是以广播的方式发送,但是要寻找的地址却不是qige.io的地址,而是网关地址。回应该请求的地址也是网关地址。
结论:
ARP 请求都是使用广播方式发送的。如果访问的是本子网的 IP,那么 ARP 解析将直接得到该 IP 对应的 MAC;如果访问的非本子网的 IP, 那么 ARP 解析将得到网关的 MAC。原因:
ARP代理,访问非子网IP时是通过路由器访问的,路由器再把发出去,目标IP收到请求后,再通过路由器端口IP返回去,那么ARP解析将会得到网关的MAC。
网络层
- 熟悉 IP 包结构
IP包结构图如下
使用 Wireshark 任意进行抓包,熟悉 IP 包的结构,如:版本、头部长度、总长度、TTL、协议类型等字段。
图中从上到下依次是IP包的:版本号(Version)、IP包头长度(Header Length)、服务类型(Type of Service)、IP包总长(Total Length)、标识符(Identifier)、标记(Flags)、片偏移(Fragment Offset)、生存时间(TTL) 、协议(Protocol)、头部校验(Header Checksum)、起源和目标地址(Source and Destination Addresses)。
IP 头部既有头部长度字段,也有总长度字段的原因:
头部长度字段的存在是因为ip选项的存在使得ip头部长度不固定,只有知道了头部长度才能准确定位数据的开始。
总长度字段的存在是为了便于传输时的识别IP总长度,节省时间,当长度超过1500B时就会被返回链路层进行分段。
- IP 包的分段与重组
根据规定,一个 IP 包最大可以有 64K 字节。但由于 Ethernet 帧的限制,当 IP 包的数据超过 1500 字节时就会被发送方的数据链路层分段,然后在接收方的网络层重组。
缺省的,ping 命令只会向对方发送 32 个字节的数据。我们可以使用 ping 172.19.1.2 -l 1600 命令指定要发送的数据长度。此时使用 Wireshark 抓包(用 ip.addr == 172.19.1.2 进行过滤),了解 IP 包如何进行分段,如:分段标志、偏移量以及每个包的大小等。
可以看到,帧被分成了两个部分进行传输,图中Total Length表示切割后该IP包的长度,第一个包长为1500,第二个包长为148。
Flags为标记,为001的时候表示该分段为最后一段,000则表示不是最后一个分段。
Fragment Offset为片偏移,表示该IP包在该组分片包中位置,接收端靠此来组装还原IP包。
在IPv6中,不允许分段传输,当路由器遇见很大的包时,会直接的丢掉,并返回信息,让主机自行处理。
- 考察 TTL 事件
使用 tracert www.baidu.com 命令进行追踪,此时使用 Wireshark 抓包(用 icmp 过滤),分析每个发送包的 TTL 是如何进行改变的,从而理解路由追踪原理。
部分过程如上图,可以看出,路由追踪的原理是:每到达一个节点,就返回一个信息,随之TTL也逐渐增加,每次增加1,直至目的主机为止。
IPv4 中,TTL 虽然定义为生命期即 Time To Live,但现实中我们都以跳数/节点数进行设置。如果你收到一个包,其 TTL 的值为 50,那么可以推断这个包从源点到你之间有50跳。
传输层
TCP 和 UDP 段结构
TCP 段的结构
- 16位端口号:告知主机该报文段来自哪里(源端口)以及传给哪个上层协议或应用程序(目的端口)的。进行tcp通信时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号。
- 32位序号:一次tcp通信过程中某一个传输方向上的字节流的每个字节的编号。假设主机A和主机B进行tcp通信,A发送给B的第一个tcp报文段中,序号值被系统初始化为某个随机值ISN。那么在该传输方向上(从A到B),后续的tcp报文段中序号值将被系统设置成ISN加上该报文段所携带数据的第一个在整个字节流中的偏移。例如,某个tcp报文段传送的数据时字节流中的第1025~2048字节,那么该报文段的序号值就是ISN+1025。另一个传输方向(从B到A)的tcp报文段的序号值也具有相同的含义。
- 32位确认号:用作对另一方发送来的tcp报文段的相应。其值是收到的tcp报文段的序号值加1。假设主机A和主机B进行tcp通信,那么A发送出的tcp报文段不仅携带自己的序号,而且包含对B发送来的tcp报文段的确认号。反之,B发送出的tcp报文段也同时携带自己的序号和对A发送来的报文的确认号。
- 4位头部长度:标识该tcp头部有多少个32bit字(4字节)因为4位最大能表示15,所以tcp头部最长是60字节。
- 6位标志位(即图中的保留6位):标志位有如下几项
- URG标志,表示紧急指针是否有效
- ACK标志,表示确认号是否有效。称携带ACK标志的tcp报文段位确认报文段
- PSH标志,提示接收端应用程序应该立即从tcp接受缓冲区中读走数据,为接受后续数* 据腾出空间(如果应用程序不将接收的数据读走,它们就会一直停留在tcp缓冲区中)
- RST标志,表示要求对方重新建立连接。携带RST标志的tcp报文段为复位报文段。
- SYN标志,表示请求建立一个连接。携带SYN标志的tcp报文段为同步报文段。
- FIN标志,表示通知对方本端要关闭连接了。携带FIN标志的tcp报文段为结束报文段。
- 16位窗口大小:是tcp流量控制的一个手段。这里说的窗口,指的是接收通告窗口。它告诉对方本端的tcp接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
- 16位校验和:由发送端填充,接收端对tcp报文段执行CRC算法以校验tcp报文段在传输过程中是否损坏。注意,这个校验不仅包括tcp头部,也包括数据部分。这也是tcp可靠传输的一个重要保障。
- 16位紧急指针:是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一个字节的序号。因此,确切的说,这个字段是紧急指针相对当前序列号的偏移,称为紧急偏移。tcp的紧急指针是发送端向接收端发送紧急数据的方法。
①用 Wireshark 任意抓包(可用 tcp 过滤),熟悉 TCP 段的结构,如:源端口、目的端口、序列号、确认号、各种标志位等字段
图中源端口号:51336、目的端口号:443、位序号:1095 、确认号:7071、头部长度:20、标志位:000000010000、 窗口大小:1022、校验和:0x4434、紧急指针:0UDP 段结构
- 源端口:源端口号。在需要对方回信时选用。不需要时可用全0。
- 目的端口:目的端口号。这在终点交付报文时必须要使用到。
- 长度: UDP用户数据报的长度,其最小值是8(仅有首部)。
- 校验和:检测UDP用户数据报在传输中是否有错。有错就丢弃。
②用 Wireshark 任意抓包(可用 udp 过滤),熟悉 UDP 段的结构,如:源端口、目的端口、长度等
图中源端口:61440、目的端口:61440、长度:48、校验和:0x9395
UDP 的头部比 TCP 简单得多,但两者都有源和目的端口号。源端口是指发送数据包的一方的端口,目的端口是指接受数据包的一方的端口,端口可以用来识别发送方和接收方,便于实现程序之间的通信。
分析 TCP 建立和释放连接
- 打开浏览器访问 qige.io 网站,用 Wireshark 抓包(可用 tcp 过滤后再使用加上 Follow TCP Stream),不要立即停止 Wireshark 捕获,待页面显示完毕后再多等一段时间使得能够捕获释放连接的包。
- 请在你捕获的包中找到三次握手建立连接的包,并说明为何它们是用于建立连接的,有什么特征。
三次握手:
① 第一次握手:计算机发送的TCP报文中以[SYN]作为标志位,Seq=0;
② 第二次握手:服务器返回的TCP报文中以[SYN,ACK]作为标志位;Seq=0;Ack=1(第一次握手中Seq的值+1);
③ 第三次握手:计算机再向服务器端发送的TCP报文中以[ACK]作为标志位;Seq=1(第二次握手中Ack的值);Ack=1(第二次握手中Seq的值+1)。
④ 建立连接成功
其中Seq为序号,Ack为确认号;SYN标志表示请求建立一个连接;ACK标志表示确认号是否有效。因此它们是用于建立连接的。
- 请在你捕获的包中找到四次挥手释放连接的包,并说明为何它们是用于释放连接的,有什么特征。
四次挥手:
① 一次挥手:TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
② 二次挥手:服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。
③ 服务器关闭客户端的连接。
④ 三次挥手:服务器发送一个FIN给客户端。
⑤ 四次挥手:客户端发回ACK报文确认,并将确认序号设置为收到序号加1。
FIN标志表示通知对方本端要关闭连接了,ACK标志表示确认号是否有效。因此它们是用于释放连接的。
去掉 Follow TCP Stream,即不跟踪一个 TCP 流,你可能会看到访问 qige.io 时我们建立的连接有多个,是因为们之间的连接是属于短连接,一旦数据发送完成后,就会断开连接。但是即使断开连接,缓存依旧存在。这样的连接的作用是实现多个用户进行访问,可以达到节省通道使用的作用,提高利用率。
释放连接需要四次挥手,有时可能会抓到只有三次挥手,是因为第二次挥手和第三次挥手合并了。如果对方仍然有数据发送,那么等数据发完,再发FIN关闭连接,此时才是正常的四次挥手。
应用层
- 了解 DNS 解析
先使用 ipconfig /flushdns 命令清除缓存,再使用 nslookup qige.io 命令进行解析,同时用 Wireshark 任意抓包。
应该可以看到当前计算机使用 UDP,向默认的 DNS 服务器的 53 号端口发出了查询请求,而 DNS 服务器的 53 号端口返回了结果
对同一个站点,我们发出的 DNS 解析请求不止一个,其原因是这个网站设有好几个计算机,每一个计算机都运行同样的服务器软件。这些计算机的IP地址不一样的,但它们的域名却是相同的。这样,第一个访问该网址的就得到第一个计算机的IP地址,而第二个访问者就得到第二个计算机的IP地址等等,这样可使每一个计算机的负荷不会太大。
- 了解 HTTP 的请求和应答
① 打开浏览器访问 qige.io 网站,用 Wireshark 抓包(可用http 过滤再加上 Follow TCP Stream),不要立即停止 Wireshark 捕获,待页面显示完毕后再多等一段时间以将释放连接的包捕获。
② 在捕获的包中找到 HTTP 请求包
请求的头部的字段及其意义
1.安全性:get的安全性较低,post的较高
2.传送量:get的传送量只有小于2kb,而post的大小在理论上不受限制
3.get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段——对应,在URL中可以看到。而post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
4.get一般用于获取服务端数据的时候(获取)。而post一般用于大量数据提交的情况下,比如表单提交,文件上传等(提交)
③ 在你捕获的包中找到 HTTP 应答包
1.200(OK):请求成功。一般用于GET与POST请求
2.301(Moved Permanently):资源被永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI。
3.302(Found):资源临时移动。资源只是临时被移动,客户端应继续使用原有URI
4.304:用其他策略获取资源
5.403(Forbidden):没权限。服务器收到请求,但拒绝提供服务
6.404(Not Found):请求的资源不存在。遇到404首先检查请求url是否正确
刷新一次 qige.io 网站的页面同时进行抓包,你发现不少的 304 代码的应答,这是所请求的对象没有更改的意思,让浏览器使用本地缓存的内容即可。服务器回答 304 应答而不是常见的 200 应答的原因:
因为浏览器要判断文件有无修改,和cache结果是否一致。这要经过以下几个状态:
- 初始状态
第一次访问时,向服务器发送请求,成功收到响应,返回200,浏览器下载资源文件,并记录下response header和返回时间。- 再次请求相同资源
再次访问相同资源时,本地先判断是否需要发送请求给服务端:比较当前时间和上一次返回200时的时间差,如果未超过过期时间,则命中强缓存,读取本地缓存资源。如果过期了,则向服务器发送header带有If-None-Match和If-Modified-Since的请求- 服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;
- 如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;