数据链路层
实作一 熟悉 Ethernet 帧结构
使用 Wireshark 任意进行抓包,熟悉 Ethernet 帧的结构,如:目的 MAC、源 MAC、类型、字段等。
✎ 问题
你会发现 Wireshark 展现给我们的帧中没有校验字段,请了解一下原因。
在Wireshark抓包之前,物理层网卡已经把前面几层加上去的一些东西去掉了,比如前导同步码、FCS等等,之后利用校验码CRC校验,正确的时候才会进行下一步的操作,这时才开始抓包,所以抓包软件抓到的是去掉前导同步码、FCS以外的数据,没有校验字段。
实作二 了解子网内/外通信时的 MAC 地址
ping
你旁边的计算机(同一子网),同时用 Wireshark 抓这些包(可使用 icmp 关键字进行过滤以利于分析),记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址是多少?这个 MAC 地址是谁的?- 然后
ping qige.io
(或者本子网外的主机都可以),同时用 Wireshark 抓这些包(可 icmp 过滤),记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址是多少?这个 MAC 地址是谁的? - 再次
ping www.cqjtu.edu.cn
(或者本子网外的主机都可以),同时用 Wireshark 抓这些包(可 icmp 过滤),记录一下发出帧的目的 MAC 地址以及返回帧的源 MAC 地址又是多少?这个 MAC 地址又是谁的?
2.
3、
✎ 问题
通过以上的实验,你会发现:
访问本子网的计算机时,目的 MAC 就是该主机的
访问非本子网的计算机时,目的 MAC 是网关的
请问原因是什么?答:因为子网内的计算机是可以通过交换机直接访问的,所以目的MAC可得知就是目的主机的,如果是非本子网的计算机,因为不知道其MAC地址,但访问需要通过网关转发和接收,所以就填网关的MAC地址。
实作三 掌握 ARP
- 为防止干扰,先使用
arp -d *
命令清空 arp 缓存 ping
你旁边的计算机(同一子网),同时用 Wireshark 抓这些包(可 arp 过滤),查看 ARP 请求的格式以及请求的内容,注意观察该请求的目的 MAC 地址是什么。再查看一下该请求的回应,注意观察该回应的源 MAC 和目的 MAC 地址是什么。- 再次使用
arp -d *
命令清空 arp 缓存 - 然后
ping qige.io
(或者本子网外的主机都可以),同时用 Wireshark 抓这些包(可 arp 过滤)。查看这次 ARP 请求的是什么,注意观察该请求是谁在回应。
✎ 问题
通过以上的实验,你应该会发现,
- ARP 请求都是使用广播方式发送的
- 如果访问的是本子网的 IP,那么 ARP 解析将直接得到该 IP 对应的 MAC;如果访问的非本子网的 IP, 那么 ARP 解析将得到网关的 MAC。
请问为什么?
因为如果是访问本子网的ip,可以直接访问,所以ARP解析获取的就是对应ip的MAC,但如果是访问非本子网的ip时是需要经过网关发出去然后通过路由器访问,目标IP收到请求再通过路由器到达网关返回,所以ARP解析获取的就是网关的MAC。
网络层
实作一 熟悉 IP 包结构
使用 Wireshark 任意进行抓包(可用 ip 过滤),熟悉 IP 包的结构,如:版本、头部长度、总长度、TTL、协议类型等字段。
✎ 问题
为提高效率,我们应该让 IP 的头部尽可能的精简。但在如此珍贵的 IP 头部你会发现既有头部长度字段,也有总长度字段。请问为什么?
因为头部长度是为了让接受方知道报头在哪里结束和读取数据在哪里开始。总长度是为了让接受方的网络层了解传输的数据包含哪些,如果没有这部分,数链层在传输时会对数据进行长度的填充,对应的网络层不会把填充的部分去掉。
实作二 IP 包的分段与重组
我们可以使用 ping 202.202.240.16 -l 2000
命令指定要发送的数据长度。此时使用 Wireshark 抓包(用 ip.addr == 202.202.240.16
进行过滤),了解 IP 包如何进行分段,如:分段标志、偏移量以及每个包的大小等
✎ 问题
分段与重组是一个耗费资源的操作,特别是当分段由传送路径上的节点即路由器来完成的时候,所以 IPv6 已经不允许分段了。那么 IPv6 中,如果路由器遇到了一个大数据包该怎么办?
路由器会把该数据包丢掉或者转发到支持该数据包传输的路由上。
实作三 考察 TTL 事件
请使用 tracert www.baidu.com
命令进行追踪,此时使用 Wireshark 抓包(用 icmp
过滤),分析每个发送包的 TTL 是如何进行改变的,从而理解路由追踪原理。
✎ 问题
在 IPv4 中,TTL 虽然定义为生命期即 Time To Live,但现实中我们都以跳数/节点数进行设置。如果你收到一个包,其 TTL 的值为 50,那么可以推断这个包从源点到你之间有多少跳?
64-50=14跳
传输层
实作一 熟悉 TCP 和 UDP 段结构
- 用 Wireshark 任意抓包(可用 tcp 过滤),熟悉 TCP 段的结构,如:源端口、目的端口、序列号、确认号、各种标志位等字段。
- 用 Wireshark 任意抓包(可用 udp 过滤),熟悉 UDP 段的结构,如:源端口、目的端口、长度等。
✎ 问题
由上大家可以看到 UDP 的头部比 TCP 简单得多,但两者都有源和目的端口号。请问源和目的端口号用来干什么?
端口标识唯一的进程,源端口代表发起通信的进程,目的端口代表接收通信的进程。源端口和目的端口的存在,才可以实现程序之间的通信。
实作二 分析 TCP 建立和释放连接
- 打开浏览器访问 qige.io 网站,用 Wireshark 抓包(可用 tcp 过滤后再使用加上
Follow TCP Stream
),不要立即停止 Wireshark 捕获,待页面显示完毕后再多等一段时间使得能够捕获释放连接的包。 - 请在你捕获的包中找到三次握手建立连接的包,并说明为何它们是用于建立连接的,有什么特征。
- 请在你捕获的包中找到四次挥手释放连接的包,并说明为何它们是用于释放连接的,有什么特征。
三次握手:建立 TCP 连接需要通信的双方先完成“三次握手”连接,连接中的一对 Socket 是由互联网地址标志符和端口组成的,窗口大小主要用来做流控制,序列号是用来追踪通信发起方发送的数据包序号,接收方可以通过序列号向发送方确认某个数据包的成功接收,并且前两次握手发的包中SYN=1,只有最后一次握手SYN=0.
四次挥手:
(1)第一次挥手:甲方发送FIN包给乙方表明断开连接,但这只是代表甲方不会再发了,但依然可以接收乙方数据(FIN,ACK=1)
(2)第二次挥手:乙方任然还有数据需要发,则先发ACK包,表明收到甲方发出的FIN包,防止甲方没收到回复而不断发FIN包的情况(ACK=1)
(3)第三次挥手:乙方没有数据需要发,则发FIN包给甲方,表明通信结束,发出FIN包后则进入LAST_ACK即超时等待阶段。(FIN,ACK=1)
(4)第四次挥手:甲方收到FIN包后向乙方及时发送ACK包也确认连接中断,这时乙方才释放连接(ACK=1)
✎ 问题一
去掉
Follow TCP Stream
,即不跟踪一个 TCP 流,你可能会看到访问qige.io
时我们建立的连接有多个。请思考为什么会有多个连接?作用是什么?因为他们之间的连接是短连接,一旦数据发送就会断开,但页面由于缓存所以依然存在,如果需要重新发送数据就需要再次链接。这样连接是为了容纳多个用户同时访问,可以节省访问的通道被长期占用。
✎ 问题二
我们上面提到了释放连接需要四次挥手,有时你可能会抓到只有三次挥手。原因是什么?
因为第二次握手和第三次握手合并了,如果对方没有数据发给本端,那么对方也会发FIN给本端,这样ACK和FIN就可能出现在一起导致握手合并了。
应用层
实作一 了解 DNS 解析
- 先使用
ipconfig /flushdns
命令清除缓存,再使用nslookup qige.io
命令进行解析,同时用 Wireshark 任意抓包(可用 dns 过滤)。 - 你应该可以看到当前计算机使用 UDP,向默认的 DNS 服务器的 53 号端口发出了查询请求,而 DNS 服务器的 53 号端口返回了结果。
- 可了解一下 DNS 查询和应答的相关字段的含义
✎ 问题
你可能会发现对同一个站点,我们发出的 DNS 解析请求不止一个,思考一下是什么原因?
因为这样可以减轻服务器的负载,可能有多个计算机承载着同一服务器,虽然他们ip不同,但却是同一域名,所以访问时可能是不同计算机的ip,并且可以均衡每台计算机的负荷。
实作二 了解 HTTP 的请求和应答
- 打开浏览器访问 qige.io 网站,用 Wireshark 抓包(可用http 过滤再加上
Follow TCP Stream
),不要立即停止 Wireshark 捕获,待页面显示完毕后再多等一段时间以将释放连接的包捕获。 - 请在你捕获的包中找到 HTTP 请求包,查看请求使用的什么命令,如:
GET, POST
。并仔细了解请求的头部有哪些字段及其意义。 - 请在你捕获的包中找到 HTTP 应答包,查看应答的代码是什么,如:
200, 304, 404
等。并仔细了解应答的头部有哪些字段及其意义。
✎ 问题
刷新一次 qige.io 网站的页面同时进行抓包,你会发现不少的
304
代码的应答,这是所请求的对象没有更改的意思,让浏览器使用本地缓存的内容即可。那么服务器为什么会回答304
应答而不是常见的200
应答?因为浏览器和服务器可以先进行协商,服务器通知浏览器当前请求资源上一次修改的时间,浏览器第二次发送请求时,本地会先和之前的缓存作比较,如果过期则向服务器发送请求,服务器收到请求后判断资源有无变动,若无则返回304,有则返回新资源和200