1. ARP 协议概述
 
当我们在互联网上发送数据包时,我们需要知道接收方的 IP 地址。路由器依赖于 IP 地址来决定如何将数据包导向其最终目的地。然而,当一台计算机向同一本地网络内的另一台计算机发送数据包时,仅知道接收者的 IP 地址是不够的,因为接收者的网卡只会检查以太网帧头中的 MAC 地址来判断它是否是接收方。因此,发送者需要在头部中放置接收者的 MAC 地址。问题是,对一个给定的 IP 地址,我们如何知道其对应的 MAC 地址?
 

这通过 ARP 协议来完成。ARP是一个第2层的协议。该协议非常简单:如果一台计算机需要查找 IP 地址 X 对应的 MAC 地址,它会向整个网络发送一个广播消息,询问 “谁拥有 IP 地址 X?请告诉我”。 所有连接在同一局域网上的计算机都会收到这个消息。持有 IP 地址 X 的那个机器会给出回复,提供自身的 MAC 地址。下图描述了此协议的工作方式。
 
ARP 协议
 
让我们通过实验来看 ARP 是如何工作。我们去设置中的主机 10.9.0.5,并使用 tcpdump 监控网络接口 eth0 上的网络流量。然后,我们在另一个主机 10.9.0.6 运行 ping 10.9.0.5 命令。我们会看到以下结果:
// 在 10.9.0.5 上
# tcpdump -i eth0 -n
03:10:44.656336  ARP, Request who-has 10.9.0.5 tell 10.9.0.6, ...
03:10:44.656362  ARP, Reply 10.9.0.5 is-at 02:42:0a:09:00:05, ...
03:10:44.656382 IP 10.9.0.6 > 10.9.0.5: ICMP echo request, ...
03:10:44.656392 IP 10.9.0.5 > 10.9.0.6: ICMP echo reply, ...
在 ping 数据包(ICMP)发送出去之前,主机10.9.0.6} 需要知道 10.9.0.5 的 MAC 地址,因此它向网络中的所有人发出 ARP 请求。我们可以看到 10.9.0.5 发送了一个带有 MAC 地址的 ARP 回复。之后,ping 的数据包才会被发送出去。
 
2. ARP 消息格式
ARP 协议设计用于将网络层地址转换为链路层地址(反之亦然)。它并不局限于任何特定类型的地址。例如,网络层地址可以是 IPv4 或 IPv6 地址。因为这些地址类型各不相同,因此 ARP 消息的大小依赖于链路层和网络层地址的长度。ARP 消息头部中有两个字段指明了每个地址的长度。

下图展示了如果网络层地址是 IPv4 而链路层地址是以太网地址时 ARP 消息格式。请求和回复消息的格式相同。

ARP 头
 
ARP 请求。对于 ARP 请求,发送方会填充发件人部分(包括 IP 地址和 MAC 地址),以及目标部分中的 IP 地址。目标 MAC 地址被留空,因为这正是发送者想要知道的内容。操作代码为 1。

ARP 回复。当目标 IP 的拥有者看到 ARP 请求时,它会构造一个 ARP 回复消息,在发件人部分中放入自己的信息,并从 ARP 请求信息中复制发件人的地址到目标部分。回复的操作代码设置为 2。

3. ARP 缓存
在发送每个数据包之前都发出广播 ARP 消息会浪费大量的带宽。为了避免这种情况,ARP 使用了缓存机制。每次收到回答时,它都会将回答在缓存中存一段时间。当下次要向同一 IP 地址发送数据包时,MAC 地址将会从缓存中得到,而不是通过再次发出 ARP 请求来得到。缓存中的条目能停留多久取决于系统设置。

我们可以使用 arp 命令列出和修改缓存内容。以下实验展示了在发出 ping 10.9.0.6 命令前后缓存的内容。命令运行之前,缓存为空。当我们运行 ping 10.9.0.6 时,计算机不知道 10.9.0.6 的 MAC 地址,因此会发出 ARP 请求。从下面可以看到,ARP 的结果被缓存了。

# arp -n
# ping 10.9.0.6
PING 10.9.0.6 (10.9.0.6) 56(84) bytes of data.
64 bytes from 10.9.0.6: icmp_seq=1 ttl=64 time=0.138 ms
...
# arp -n
Address    HWtype  HWaddress           Flags Mask  Iface
10.9.0.6   ether   02:42:0a:09:00:06   C           eth0  
                           已缓存的MAC地址
 
我们还可以使用 arp 命令来设置和删除 ARP 条目。在以下内容中,我们将为 10.9.0.7 设置一个 ARP 条目(此条目不会过期;它带有 M 标记)。我们也展示了如何使用 arp 命令删除一个 ARP 条目。
# arp -s 10.9.0.7 aa:bb:cc:dd:ee:ff
# arp -n
Address    HWtype  HWaddress           Flags Mask  Iface
10.9.0.7   ether   aa:bb:cc:dd:ee:ff   CM          eth0  
10.9.0.6   ether   02:42:0a:09:00:06   C           eth0

# arp -d 10.9.0.7
# arp -n
Address    HWtype  HWaddress           Flags Mask  Iface
10.9.0.6   ether   02:42:0a:09:00:06   C           eth0  
Last modified: Wednesday, 4 June 2025, 10:54 AM