网络实验:观察ARP协议通信过程

本节,我们用一个极简的局域网,来观察 ARP 协议的通信步骤,以此加深理解:

实验环境由 Docker 容器提供,只需执行这个 docker 命令,即可一键启动:

1
docker run --name lan --rm -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -v /data fasionchan/netbox:0.11 launch-netenv lan

先来认识一个新命令—— arp ,它用来查看系统 ARP 缓存的:

1
root@ant [ ~ ]  ➜ arp -n

刚开始时,主机 antARP 缓存是空的。如果它现在使用 IP 协议向 bee 发送数据,就会触发 ARP 地址解析。我们可以在 antping 主机 bee ,来观察 ARP 地址解析的全过程。

开始之前,我们先在主机 bee 上执行 tcpdump 命令,观察 eth0 网卡上的流量:

1
root@bee [ ~ ]  ➜ tcpdump -nei eth0

现在,我们回到主机 ant ,执行命令 ping 主机 beebeeIP 地址是 192.168.1.2

-c 指示 ping 命令,只发一个 IP 包进行探测。

1
2
3
4
5
6
7
root@ant [ ~ ]  ➜ ping -c 1 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.550 ms

--- 192.168.1.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.550/0.550/0.550/0.000 ms

ping 命令的输出我们获取,它成功发出一个 ping 包,并受到 bee 的应答,往返耗时 0.55 毫秒。

在 bee 主机上,我们观察到这次通信的整个过程:

1
2
3
4
5
6
7
root@bee [ ~ ]  ➜ tcpdump -nei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
19:10:24.379278 40:aa:aa:aa:aa:aa > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.2 tell 192.168.1.1, length 28
19:10:24.379419 40:bb:bb:bb:bb:bb > 40:aa:aa:aa:aa:aa, ethertype ARP (0x0806), length 42: Reply 192.168.1.2 is-at 40:bb:bb:bb:bb:bb, length 28
19:10:24.379469 40:aa:aa:aa:aa:aa > 40:bb:bb:bb:bb:bb, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 192.168.1.2: ICMP echo request, id 509, seq 1, length 64
19:10:24.379507 40:bb:bb:bb:bb:bb > 40:aa:aa:aa:aa:aa, ethertype IPv4 (0x0800), length 98: 192.168.1.2 > 192.168.1.1: ICMP echo reply, id 509, seq 1, length 64

tcpdump 输出第一行,正是 ant 发出 ARP 解析请求。为了得到 192.168.1.2MAC 地址,ant 向整个网络广播了 ARP 请求。就像在人群中大喊一声,谁是 192.168.1.2 ,快把 MAC 地址告诉我!

tcpdump 输出第二行,则是 bee 发出的 ARP 应答。它收到 ant 的询问,立马回答道:我就是 192.168.1.2 ,我的 MAC 地址是 40:bb:bb:bb:bb:bb

回到主机 ant ,再次执行 arp 命令查看 ARP 缓存,我们发现多了一条关于主机 bee 的记录:

1
2
3
root@ant [ ~ ]  ➜ arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.1.2              ether   40:bb:bb:bb:bb:bb   C                     eth0

ant 收到 ARP 应答后,就可以封装以太网帧,将 IP 包发给 192.168.1.2 了,见 tcpdump 输出第三行。 192.168.1.2 马上发出另一个 IP 包,对 antping 进行响应,将 tcpdump 输出第四行。

为什么主机 bee 不需要发起 ARP 解析,就知道 192.168.1.1MAC 地址呢?

原来,ant 将自己的 IPMAC 地址都附在 ARP 请求报文中,bee 收到请求后,也就知道 192.168.1.1MAC 地址了。主机 beeARP 缓存也从侧面证实了这一点:

1
2
3
root@bee [ ~ ]  ➜ arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.1.1              ether   40:aa:aa:aa:aa:aa   C                     eth0

某些情况下,为了强制进行 ARP 地址解析,需要将 ARP 缓存清空。这可以通过执行 ip 命令来完成:

1
ip -s -s neigh flush all

Wireshark分析

tcpdump 是一个功能非常强大的抓包工具,但显示并不是很方便。

Wireshark 是另一个抓包神器,它自带强大的图形界面,来做协议分析非常方便。由于 WiresharkGUI 软件,而服务器一般不带 GUI ,因此无法直接在服务器上用它来抓包。

尽管如此,我们可以使用 tcpdump 来抓包,并将数据保存到文件,再用 Wireshark 来分析数据:

1
2
3
4
5
root@bee [ ~ ]  ➜ tcpdump -nei eth0 -w /tmp/arp-lab.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C4 packets captured
4 packets received by filter
0 packets dropped by kernel

-w 选项指定数据写入文件的路径。抓包完毕后,按 Ctrl-C 即可退出 tcpdump 命令,它保存好数据后将输出一些统计信息。

之后,我们可以使用 Wireshark ,打开 tcpdump 生成的 pcap 格式文件。本节实验抓到的 ARP 通信步骤数据可以从 Github 获取,将其打开后可看到这个界面:

界面中上方显示我们抓到的包,总共有 4 个,每个一行。每行显示包的源地址、目的地址以及协议类型等信息,跟 tcpdump 命令输出的差不多。

点击其中一个包(比如第一个),我们可以在中部看到该包的详情:这是一个 ARP 报文,承载在以太网帧之上。详情中可以查看到以太网帧以及 ARP 报文的各个字段,不再一一赘述。

下方则是该包的原始数据,这是一个字节序列:左边是每个字节的十六进制值;右边是每个字节的 ASCII 码,. 表示该字节不可显示。

Wireshark 是一个非常有用的工具,后续我们还会经常用到。上手这个软件并没有难度,请大家自行摸索。

扩展阅读

小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: