目录
- 这是本人计网 Wireshark 的报告,抓包过程参考了 Computer Networking: A Top-Down Approach,希望可以帮大家少走弯路~
以太网帧
- 下面将分析包含 HTTP 请求与应答报文的以太网帧
抓包过程
- 首先清空浏览器缓存 (
Tools
->Clear Recent History
),然后打开 Wireshark 分组嗅探器 - 在浏览器中访问如下 URL:
http://gaia.cs.umass.edu/wireshark-labs/HTTP-ethereal-lab-file3.html - 停止抓包,找到其中 HTTP GET 以及 HTTP 响应报文对应的 Wireshark 包序号,如下图所示,HTTP GET 报文序号为 73,HTTP 响应报文序号为 78,下面就分别分析包含这两个报文的以太网帧
- 因为目前只分析数据链路层,因此可以屏蔽网络层及更高层:在
Analyze->Enabled Protocols
中选择禁用 IPv4,效果如下:
包含 HTTP 请求报文的以太网帧
- 帧结构如下图所示,可以看到,源地址为
b8:08:cf:b2:0d:63
,目的地址为58:69:6c:91:13:ba
,类型字段为0x0800
表示上层协议为 IPv4,而以太网帧中的数据字段也可以看到有GET...
的 ASCII 码字符,说明该以太网帧包含了 HTTP 请求报文
- 在发送 HTTP 请求报文时,肯定是从主机发往远端的 Web 服务器,该服务器并不在我主机的局域网上,因此在网络层,主机通过查路由表发现无法直接交付,所以将 IP 数据报发往默认路由,下一跳地址肯定为默认路由的 IP 地址,而该 IP 地址又通过 ARP 协议转为默认路由的 MAC 地址填入以太网帧的目的地址中。因此,在数据链路层,源 MAC 地址一定为主机的 MAC 地址,而目的 MAC 地址则为默认路由的 MAC 地址,下面进行验证
查看主机 MAC 地址
- 在命令行中输入
ipconfig /all
,由下图可以看出,主机的 MAC 地址确实为b8:08:cf:b2:0d:63
,与预期相符
查看默认路由的 MAC 地址
- 由上图也可以看出,默认路由的 IP 地址为
10.5.0.1
。继续输入命令arp -a
,在 ARP 高速缓存中查找该 IP 地址对应的 MAC 地址:
- 可以看出,默认路由的 MAC 地址也确实为
58:69:6c:91:13:ba
,与预期相符,说明分析正确
包含 HTTP 响应报文的以太网帧
- 帧结构如下图所示,可以看到,类型字段为
0x0800
表示上层协议为 IPv4;源地址为58:69:6c:91:13:ba
,目的地址为b8:08:cf:b2:0d:63
,HTTP 响应报文是从 Web 服务器发往主机的,而最后肯定是由默认路由直接交付给主机,帧中的源地址和目的地址也确实分别为默认路由的 MAC 地址和主机的 MAC 地址
- 数据字段:以太网帧中的数据字段也可以看到有
when in actual...
的 ASCII 码字符,如下图所示,这段话在我刚才打开的网页中,说明该以太网帧包含了 HTTP 响应报文,其中含有 Web 服务器返回给浏览器的 HTML 文档内容
ARP
- ARP 报文格式如下:
查看主机网络配置
- 如下图所示,我目前的 IP 地址为
10.6.18.125
,MAC 地址与之前一样,为b8:08:cf:b2:0d:63
抓包过程
- 清空 ARP 高速缓存:在命令行中输入
arp -d *
- 打开分组嗅探器,先看一下当前局域网上有哪些其他活动的主机,如下图所示,发现
10.6.85.58
是活跃的
ping 10.6.85.58
,然后停止抓包
- 虽然 ARP 也是网络层协议,但它是直接封装在以太网帧中的,因此同样的,可以在
Analyze->Enabled Protocols
中选择禁用 IPv4 以屏蔽高层协议。在其中找到查询10.6.85.58
对应 MAC 地址的 ARP 请求与响应报文,如下图所示,已用蓝色标记出来
ARP 请求报文
- 报文结构如下,可以看到,ARP 报文被直接封装在以太网帧中
- 先看 ARP 请求报文 的内容:硬件类型为 1,表示发送端的物理网络类型为 Ethernet;协议类型为 0x0800,表示网络层协议为 IPv4;硬件地址长度为 6,表示使用 48 位的 MAC 地址;协议地址长度为 4,表示使用 32 位的 IPv4 地址;操作类型为 1,表示为 ARP 请求报文;发送者 MAC 地址为
b8:08:cf:b2:0d:63
,这是我主机的 MAC 地址;发送者 IP 地址为10.6.18.125
,这是我主机目前的 IP 地址;目的 MAC 地址为空;目的 IP 地址为10.6.85.58
,表示要查询该 IP 地址对应的 MAC 地址 - 再看 以太网帧 的内容:目的 MAC 地址全 1,表示广播地址,源 MAC 地址为我主机的 MAC 地址,协议类型为 0x0806,表示上层协议为 ARP
- 先看 ARP 请求报文 的内容:硬件类型为 1,表示发送端的物理网络类型为 Ethernet;协议类型为 0x0800,表示网络层协议为 IPv4;硬件地址长度为 6,表示使用 48 位的 MAC 地址;协议地址长度为 4,表示使用 32 位的 IPv4 地址;操作类型为 1,表示为 ARP 请求报文;发送者 MAC 地址为
ARP 应答报文
- 报文结构如下,可以看到,ARP 报文被直接封装在以太网帧中
- 先看 ARP 应答报文 的内容:硬件类型为 1,表示发送端的物理网络类型为 Ethernet;协议类型为 0x0800,表示网络层协议为 IPv4;硬件地址长度为 6,表示使用 48 位的 MAC 地址;协议地址长度为 4,表示使用 32 位的 IPv4 地址;操作类型为 2,表示为 ARP 应答报文;发送者 MAC 地址为
58:69:6c:91:13:ba
,为应答节点的 MAC 地址,这也就是之前发送 ARP 请求报文时想要查询的 MAC 地址;发送者 IP 地址为10.6.85.58
,为应答节点的 IP 地址;目的 MAC 地址为b8:08:cf:b2:0d:63
,这是我主机的 MAC 地址;目的 IP 地址为10.6.18.125
,这是我主机目前的 IP 地址 - 再看 以太网帧 的内容:目的 MAC 地址为
b8:08:cf:b2:0d:63
,不再是广播地址,而是直接单播到我的主机,源 MAC 地址为58:69:6c:91:13:ba
,为应答节点的 MAC 地址,协议类型为 0x0806,表示上层协议为 ARP
- 先看 ARP 应答报文 的内容:硬件类型为 1,表示发送端的物理网络类型为 Ethernet;协议类型为 0x0800,表示网络层协议为 IPv4;硬件地址长度为 6,表示使用 48 位的 MAC 地址;协议地址长度为 4,表示使用 32 位的 IPv4 地址;操作类型为 2,表示为 ARP 应答报文;发送者 MAC 地址为
ICMP
分组网间探测 ping
ping
的工作原理
ping
使用了 ICMP 回送请求与回送回答报文来测试两台主机之间的连通性- 首先 PC 发出若干个 ICMP 回送请求报文
- 如果目标网站正常工作而且响应这个 ICMP 回送请求报文, 那么它就发回 ICMP 回送回答报文
- 由于往返的 ICMP 报文上都有时间戳, 因此很容易得出往返时间。最后显示出的是统计结果: 发送到哪个机器 (ip地址), 发送的、收到的和丢失的分组数(但不给出分组丢失的原因), 以及往返时间的最小值、最大值和平均值
抓包过程
- 打开分组嗅探器
- 输入命令
ping -n 10 www.dlut.edu.cn
来向目标主机发送 10 个 ICMP 回送请求报文并最终接收到 10 个 ICMP 回送回答报文
- 停止抓包,效果如下;可以看到,我的主机 (
10.6.18.125
) 向目标主机 (202.118.66.66
) 发送了 10 个 ICMP 回送请求报文并最终接收到 10 个 ICMP 回送回答报文,下面我们重点分析第一对回送请求和回送回答报文
ICMP 回送请求报文
- 由本地主机向目标主机发 ICMP 回送请求报文
- 如下图所示,可以清晰地看到,ICMP 报文被封装在 IP 数据报中,IPv4 数据报的协议字段为 1,表示它的上层协议为 ICMP (但其实 ICMP 是一个网络层协议)
- 下面重点关注 ICMP 报文内的内容;如下图所示,Type 字段值为 8 且 Code 字段值为 0,表示这是一个 ICMP 回送请求报文;检验和字段用来检验整个 ICMP 报文 (IP 数据报首部的检验和并不检验 IP 数据报的内容, 因此不能保证经过传输的 ICMP 报文不产生差错),检验结果为 correct;除此之外,它还有标识符以及序列号字段
ICMP 回送回答报文
- 如果目标主机正常工作而且响应这个 ICMP 回送请求报文(有的主机为了防止恶意攻击就不理睬外界发送过来的这种报文), 那么它就发回 ICMP 回送回答报文
- 如下图所示,Type 字段值为 0 且 Code 字段值为 0,表示这是一个 ICMP 回送回答报文;检验和字段的检验结果为 correct;除此之外,它还有标识符以及序列号字段
tracert
抓包过程
- 打开分组嗅探器
- 输入命令
tracert www.dlut.edu.cn
- 每一行有三个时间出现, 是因为对应每一个 TTL 值, 源主机要发送三次同样的 IP 数据报
- 还注意到, 从原则上讲, IP 数据报经过的路由器越多, 所花费的时间也会越多。但从图中可看出, 有时正好相反。这是因为互联网的拥塞程度随时都在变化, 也很难预料到。因此, 完全有这样的可能:经过更多的路由器反而花费更少的时间
- 第一行中的
10.6.0.1
正是我现在主机的默认路由地址
- 停止抓包
分析
- 可以看到,
tracert
从源主机向目的主机发送一连串的 IP 数据报,TTL 的值分别为 1、2、3 (每个 TTL 值要发三次,下面就当作每个 TTL 值只发送一个 ICMP 报文),这与上面命令的输出结果相对应。首先源主机发送的第一个数据报 (Wireshark 编号为 18) 的生存时间 TTL 设置为 1。当它到达路径上的第一个路由器时, 该路由器先收下它, 接着把 TTL 的值减 1。由于 TTL 等于零了,就把该数据报丢弃, 并向源主机发送一个 ICMP 时间超过差错报告报文;接着源主机接着发送第二个数据报, 并把 TTL 设置为 2。它先到达第一个路由器 R 1 R_1 R1 , R 1 R_1 R1 收下后把 TTL 减 1 再转发给路由器 R 2 R_2 R2。 R 2 R_2 R2 收到该数据报时 TTL 为 1 , 但减 1 后 TTL 变为零了。 R 2 R_2 R2 就丢弃该数据报, 并向源主机发送一个 ICMP 时间超过差错报告报文
- 当 TTL 设置为 3 时,发送的 ICMP 回送请求报文成功到达了目的主机,目的主机发送回 ICMP 回送回答报文 (Windows 上
tracert
的实现并不是通过发送使用了非法端口号的 UDP 用户数据报来让目的主机发回 ICMP 终点不可达差错报告报文),这样, 源主机达到了自己的目的, 因为这些路由器和最后目的主机发来的 ICMP 报文正好给出了源主机想知道的路由信息到达目的主机所经过的路由器的 IP 地址, 以及到达其中的每一个路由器的往返时间
TCP
- 下面将通过网页,利用 HTTP POST 请求报文由主机向远端服务器传送数据 (《爱丽丝梦游仙境》的一段文字)
- 我当前的 IP 地址为
10.5.61.226
抓包过程
- 下载该文件: http://gaia.cs.umass.edu/wireshark-labs/alice.txt
- 打开分组嗅探器,在浏览器中打开如下网址:http://gaia.cs.umass.edu/wireshark-labs/TCP-wireshark-file1.html
- 在网页中将 alice.txt 上传到远端服务器,传输完毕后停止抓包
- 先在过滤栏中输入 http,结果如下,可以确定远端服务器的 IP 地址为
128.119.245.12
- 在过滤栏中输入
ip.addr == 128.119.245.12
,只查看主机与该服务器的通信,效果如下:
TCP 三次握手 (连接建立)
- 我的主机 IP 地址为
10.5.61.226
,远端服务器的 IP 地址为128.119.245.12
;如下图所示,一共有三个 TCP 报文,对应三次握手的过程- 主机先向服务器发送 TCP 连接请求报文段,报头中的同步位 SYN = 1 表示建立连接;在实际的报文段中序号 seq 是随机生成的且不能为 0,但因为 Wireshark 的特殊处理,所以显式地序号是从 0 开始的
- 远端服务器处在 LISTEN 监听状态,收到接请求报文段后,发回确认。 在确认报文段,SYN = 1, ACK = 1,其确认号 ack = 1,自己选择的序号 seq = 0
- 主机收到确认报文段后向服务器发确认,其 ACK = 1,确认号 ack = 1,序号 seq = 1。此时主机的 TCP 通知上层应用进程连接已经建立。服务器的 TCP 收到主机的确认后,也通知其上层应用进程:TCP 连接已经建立
- 上面分析的过程与下图一致:
TCP 四次握手 (连接释放)
- 在我抓包的一整个流程中,我只找到了服务器主动请求释放连接的连接释放报文段及其确认,如下图所示:
- 服务器发出的连接释放报文段头部的 FIN = 1,其序号 seq = 2195,等待主机的确认。同时注意到 ACK = 1,ack = 475,说明在释放连接之前客户与服务器之间有数据传送,服务器在发出对之前数据的确认的同时请求释放连接
- 客户发出确认 ACK = 1,确认号 ack = 2196,自己的序号 seq = 475。 TCP 服务器进程收到该确认后,通知高层应用进程,从服务器到客户这个方向的连接就释放了,TCP 连接处于半关闭状态
- 四次握手的示意图如下:
TCP 端口号
- 可以看到,我主机使用的端口号为 56593,这是一个临时端口;而服务器使用的端口号为 80,这是 HTTP 协议的熟知端口号
详细分析 TCP 传送数据块的过程
- 首先在 Wireshark 中屏蔽 HTTP 协议,只显示 TCP 协议,效果如下图所示:
- 然后因为是用 HTTP POST 报文进行数据块的传送,因此这个 HTTP 报文是相当大的,不可能用一个 TCP 报文段进行传输,肯定是分成多个 TCP 报文段,因此就到这些筛选出的 TCP 报文段中找到装载了 HTTP POST 报文内容的第一个 TCP 报文段,即下图蓝色标识出的报文段,可以看到它的报文段数据部分有 POST,因此是装载了 HTTP POST 报文内容的第一个 TCP 报文段;下面就把这个 TCP 报文段当作第一个报文段,分析数据块传送的过程
- 可以看到,第一个 TCP 报文段的序号为 1,长度为 710,同时 410 号报文中,服务器向主机发送确认,ACK = 1,ack = 711 (710 + 1),即为对第一个 TCP 报文段的确认;同时可以看到,尽管从序号 711 到 13851 (400 号报文的序号为 12391,长度为 1460,12391 + 1460 = 13851) 发送方一共发送了 10 个报文段 (391 号 ~ 400 号),但接收方只返回了两个确认报文段,这是因为接收方采用的是累积确认,当在第 2 个报文段中发挥 ack = 13851 时,说明序号为 13851 之前的 TCP 报文段都已经被接收了,也就是用两个确认报文段就确认了发送方发送的 10 个报文段,效率明显提高了
- 同时经过核对,我发现所有的传送 HTTP 报文数据的 TCP 报文段的序号都是递增的,说明没有发生重传现象,网络中不存在拥塞问题
- 如下图所示,主机还收到了服务器发来的窗口值更新,用来更新发送方的通知窗口大小来进行流量控制。在下面的三个窗口更新报文段中,窗口值不断增大,说明服务器接收缓存中的一部分数据已经成功交付给了上层的应用程序,接收窗口的值增大了,因此可以允许发送方增大发送窗口,在流水线作业的情况下一次可以发送更多的数据,提高发送效率
HTTP
- 下面以 HTTP GET 报文为例进行分析
抓包过程
- 打开分组嗅探器
- 在浏览器中访问 http://gaia.cs.umass.edu/wireshark-labs/HTTP-wireshark-file1.html
- 停止抓包,过滤器中输入 http,效果如下:
HTTP 熟知端口号
- 由下图可以看出,HTTP 协议的熟知端口号为 80
HTTP 请求报文
- 可以看到,HTTP 是面向文本的,报文中的每一个字段都是一些 ASCII 码串,每个字段的长度都是不确定的
- 上面的 HTTP 请求报文中,方法为
GET
,URL 为/wireshark-labs/HTTP-wireshark-file1.html
,HTTP 协议版本为HTTP 1.1
- 首部行中也列出了 Connection (连接是否应该关闭)、User-Agent (客户程序)、Accept (客户端能够以接受的数据格式)、Accept-Encoding (客户端能够处理的编码方案)、Accept-Language (客户能够接受的语言) 等信息
- 由于是 GET,因此实体主体中没有内容
HTTP 响应报文
- 上面的 HTTP 响应报文中,HTTP 协议版本为
HTTP 1.1
,状态码为200
,短语为OK
- 首部行中列出了 Date (当前日期)、Server (服务器名与版本号)、Last-Modified (上次内容改变的时间)、ETag (正文标记)、Accept-Ranges (服务器接受客户请求的范围)、Content-Length (文档长度 128Byte)、Keep-Alive、Connection (连接是否应该关闭)、Content-Type (数据类型)
- 实体主体部分是 128Byte 的 text/html 文件,该文件就这样成功地从 Web 服务器传送到了客户的浏览器
DNS
抓包过程
- 首先清空本地的域名缓存:
ipconfig /flushdns
- 查看我当前的 IP 地址,在 Wireshark 中过滤器中输入
ip.addr == 10.6.18.125
来过滤掉那些源、目的 IP 地址都不是我主机的数据报
- 打开分组嗅探器,输入命令
nslookup www.dlut.edu.cn
向本地域名服务器发起域名解析查询
- 停止抓包。如下图所示,发现
nslookup
命令一连发送了 3 个 DNS 查询报文,分别收到了 3 个 DNS 响应报文。下面我们只关注最后的 1 个 DNS 查询报文以及 DNS 响应报文
DNS 查询报文
- DNS 查询报文的数据报结构如下,可以看到,在进行普通的域名解析时 (不是传送长报文或 DNS 服务器之间交换数据),DNS 在运输层使用的协议为 UDP,而且服务器的端口号为 53;同时从 IP 数据报中可以看出,目的 IP 地址为
202.118.66.6
,这就是本地 DNS 服务器的 IP 地址;DNS 查询报文的 查询 (Queries) 字段为www.dlut.edu.cn
,表明要查询该域名对应的 IP 地址
DNS 响应报文
- DNS 响应报文的数据报结构如下,可以看到,它在运输层同样使用 UDP 进行传输,从
202.118.66.6
(本地 DNS 服务器) 的 53 端口发出,送回到10.6.18.125
(本地主机);同时在 Answers 字段中给出了查询的结果2001:da8:a800:3::66
,即www.dlut.edu.cn
的 IPv6 地址,说明主机向本地 DNS 服务器的查询是一次递归解析 (前面说过nslookup
一共收到三个响应报文,这里分析的是最后一个,IPv4 地址在第二个响应报文中给出,分析过程与这里相同)