暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译] Linux 内核中 ARP 的内部机制

原创 Handsome BOY 2025-04-09
586

介绍

您是否曾经想过,您的计算机如何在网络上找到正确的设备来发送数据?

地址解析协议 (ARP) 使这一切成为可能。它充当 IP 地址和物理 MAC(介质访问控制)地址之间的桥梁,确保以太网中的无缝通信。虽然 IP 等高级协议使用逻辑地址,但设备实际上使用 MAC 地址进行通信。ARP 确保当一个设备知道同一本地网络上另一个设备的 IP 地址时,它可以发现相应的 MAC 地址,从而允许数据包被正确地路由和传送。

本博客旨在深入探讨 ARP 在 Linux 操作系统中的运作方式。我们将深入探讨数据包结构、Linux 内核中 ARP 的内部工作原理以及 ARP 请求和应答所涉及的流程。最终,读者将全面了解 ARP 在网络中的作用以及它在 Linux 中的实现和管理方式。

ARP基础知识

ARP功能

ARP 通过将 IP 地址(用于互联网协议)映射到 MAC 地址(用于以太网),在实现网络通信方面发挥着至关重要的作用。此映射过程至关重要,因为 IP 地址用于识别网络层的设备,而以太网等数据链路层协议则需要 MAC 地址在本地网络内转发数据包。

例如,当一个设备想要向同一网络上的另一个设备发送数据时,它首先会检查其 ARP 缓存,看看目标 IP 地址对应的 MAC 地址是否已知。如果没有,它会向网络上的所有设备广播一个 ARP 请求数据包,询问“谁拥有这个 IP 地址?” 拥有匹配 IP 地址的设备会回复其 MAC 地址,然后该地址会被缓存并用于发送数据。

ARP请求过程

当网络上的设备需要与另一台设备通信时,它需要与目标设备的 IP 地址对应的 MAC 地址来生成第 2 层报头。如果此 MAC 地址尚未缓存,设备将发起 ARP 请求。此过程基于广播,这意味着请求会发送到本地网段上的所有设备。

由于发送方尚不知道目标设备的 MAC 地址,因此 ARP 请求以广播以太网帧的形式发送。该数据包包含发送方的 IP 地址和 MAC 地址,以及目标设备的 IP 地址(目标 MAC 地址字段设置为 FF:FF:FF:FF:FF:FF)。
在 Linux 内核中,ARP 请求由 arp_send() 函数生成,该函数构造 ARP 数据包并将其广播出去。内核的网络堆栈负责确保 ARP 请求发送到正确的网络接口。
ARP应答过程
收到 ARP 请求后,网络上的所有设备都会检查数据包中的目标 IP 地址。具有匹配 IP 地址的设备会发送 ARP 应答,该应答会以单播方式直接返回给请求者。

ARP 应答包含响应设备的 MAC 地址,这使得原始发送者能够将 IP 地址映射到该 MAC 地址,并将其存储在 ARP 缓存中。此应答由 Linux 内核中的 arp_process() 函数处理。
收到 ARP 回复后,请求者会使用新的 IP 到 MAC 映射更新其 ARP 缓存。由于 MAC 地址已获知,此缓存条目允许后续通信绕过 ARP 请求过程。

ARP数据包结构

ARP 数据包由几个定义其结构和用途的字段组成:

  • 硬件类型:指定硬件地址的类型(例如以太网)。
  • 协议类型:定义协议地址的类型(例如,IPv4)。
  • 硬件大小:硬件地址的长度。
  • 协议大小:协议地址的长度。
  • 操作码:指示数据包是 ARP 请求 (1) 还是答复 (2)。
  • 发送方 MAC 地址:发送方的 MAC 地址。
  • 发件人 IP 地址:发件人的 IP 地址。
  • 目标 MAC 地址:目标接收者的 MAC 地址(在 ARP 请求中设置为 00:00:00:00:00:00)。
  • 目标 IP 地址:预期接收者的 IP 地址。

这种结构使得ARP协议能够有效地完成将IP地址解析为MAC地址的功能。

免费 ARP

免费 ARP (GARP) 是一种 ARP 消息,它不是对任何 ARP 请求的响应,而是主动以广播形式发送。它主要有两个用途:

  1. 网络公告:GARP 主动通知其他设备有关 IP-MAC 关联的变化,确保 ARP 缓存保持更新并防止过时的条目。
  2. 高可用性设置中的故障转移:在冗余配置中,两台设备可能共享相同的 IP 地址,但 MAC 地址不同。发生故障转移时,GARP 会确保网络立即更新其 ARP 缓存,从而允许与不断变化的 IP 地址进行不间断的通信。

Linux中的ARP

Linux内核中的ARP实现
在 Linux 中,ARP 是作为内核网络堆栈的一部分实现的。ARP 模块负责维护 ARP 表、处理 ARP 请求和应答,并确保 MAC 到 IP 的映射保持最新。Linux 内核主要通过 net/ipv4/arp.c 文件处理 ARP 操作,该文件定义了与 ARP 相关的一些核心函数。

ARP处理涉及的关键内核函数包括:

  • arp_send():负责制作和发送 ARP 请求。
  • arp_rcv():处理传入的 ARP 数据包,确定它们是请求还是回复,并进行相应的处理。
  • arp_process():管理更新 ARP 缓存和在必要时生成 ARP 回复的逻辑。
    Linux 还提供了一套丰富的工具和配置,允许人们控制 ARP 的运行方式,包括调整超时、缓存大小以及启用或禁用特定的 ARP 功能(如代理 ARP),这超出了我们的讨论范围。

ARP状态转换

在 Linux 中,ARP 缓存条目会根据网络活动和通信模式经历各种状态转换。每种状态都反映了 IP 到 MAC 映射的当前状态,帮助内核确定如何处理 ARP 请求、回复和探测。

主要 ARP 状态包括:

  • NONE:此状态表示不存在有效的邻居条目。
  • INCOMPLETE:内核已向指定 IP 地址发送 ARP 请求,但尚未收到回复。该条目处于临时状态,等待解析。
  • REACHABLE:IP 到 MAC 的映射已确认,且该条目正在被主动使用。该映射被视为有效,可用于数据包传输,无需进一步的 ARP 请求。
  • STALE:该条目在一段时间内未使用,因此映射可能已过期。内核不会立即将其删除,而是会在后续通信发生时将其转换为其他状态。
  • DELAY:当条目变为 STALE 状态后,如果检测到流量,它将转换为 DELAY 状态。内核将等待配置的延迟时间(由 /proc/sys/net/ipv4/neigh/default/delay_first_probe_time 控制),然后再探测该条目以检查其是否仍然有效。
  • PROBE:如果 DELAY 定时器超时且未验证,内核会发送 ARP 探测来确认 IP 到 MAC 的映射关系。在此状态下,系统会主动验证该条目。
  • FAILED:ARP 请求在多次尝试后失败,这意味着无法解析 IP 到 MAC 的映射。该条目通常会从缓存中删除。
  • 永久:此状态分配给手动配置的静态 ARP 条目,这些条目不会过期并且不受自动垃圾收集的影响。
  • 替代文本

image.png
注意:1. START 状态仅用于概念理解,并非实际 ARP 状态机的一部分。2. 上述状态图中提到的所有探测均可在 /proc/sys/net/ipv4/neigh/default/ 中找到。

ARP缓存

ARP 缓存存储了通过 ARP 请求和应答学习到的 MAC 到 IP 的映射关系。这些表由内核维护,可以使用 ip 和 arp 等用户空间工具进行查看和管理。

要查看当前的ARP表,可以使用以下命令:

ip -s neighbour

这些命令显示 IP 地址及其对应 MAC 地址的列表,以及其他信息,例如通过其学习地址的接口和条目的状态(例如,REACHABLE、STALE)。

复制代码片段
已复制到剪贴板错误:无法复制已复制到剪贴板错误:无法复制

<ip_address_1> dev <IF_1> lladdr <MAC_1> used 62/61/49 probes 1 STALE
<ip_address_2> dev <IF_2> lladdr <MAC_2> ref 1 used 6/6/6 probes 1 REACHABLE
<ip_address_3> dev <IF_3> lladdr <MAC_3> ref 1 used 0/0/213 probes 1 REACHABLE

p>输出通常包括:

  • 列出了邻居设备的IP地址和MAC 地址(lladdr)。
  • 指定邻居连接的接口(dev )。
  • 统计数据包括:
    • ref:引用计数(此条目的用户数)。
    • used:自
      最后一个数据包已发送给邻居
      收到邻居发来的最后一个数据包
    • 最后一条条目已更新。
      发送的 ARP 探测次数,用于确认邻居的可达性。
  • 显示邻居条目的状态(例如延迟、失败、不完整、noarp、无、永久、探测、可达、陈旧)。
    可以使用 ip 或 arp 命令修改 ARP 表(例如,添加或删除条目)。例如,要手动向 ARP 表添加条目,可以使用以下命令:
sudo ip neigh add <addr> lladdr <mac> dev <if_name>

ARP缓存管理

ARP 缓存中的每个条目都与特定属性相关联,包括状态、超时值以及指示内核如何处理该条目的标志。内核会自动管理缓存,方法是在收到 ARP 回复时添加新条目,并随着时间的推移删除陈旧或过期的条目。这种动态管理可确保缓存保持高效且最新。

Linux 提供了几个可调参数来控制 ARP 缓存的行为。您可以根据环境的具体要求调整这些设置以优化网络性能。

调整缓存超时

需要考虑的一个重要设置是 ARP 缓存条目的超时时间,可以通过 /proc/sys/net/ipv4/neigh/default/gc_stale_time 参数进行配置。该参数控制 ARP 条目在被标记为 STALE 之前在缓存中保留的时间。通过调整此值,您可以影响系统重新验证其 ARP 条目的频率,从而在新鲜度和资源使用率之间取得平衡。

几种场景:1. 过高(>120 秒):过时的 ARP 表项会残留,导致数据包丢失、故障转移延迟以及网络适配速度变慢。虽然这可以减少 ARP 处理开销,但可能会造成 MAC 映射过时的风险。

太低(少于 30 秒):ARP 请求变得频繁,增加了 CPU 和网络开销。但是,这可以确保在动态环境中更快地更新并提高响应速度。
选择合适的值取决于您的网络稳定性和性能需求。对于大多数设置,60 秒是一个平衡的方法。

管理缓存大小

您可以使用垃圾回收设置(例如 gc_thresh1、gc_thresh2 和 gc_thresh3)来控制 ARP 缓存的大小。这些阈值定义了 ARP 缓存可以容纳的条目的最小值、阈值和最大值。如果缓存超出这些限制,系统将开始清除旧条目,以便为新条目腾出空间。正确配置这些值有助于在内存使用率和缓存效率之间保持适当的平衡。

几种场景:

  1. 过低(gc_thresh3 < 256):ARP 缓存快速填满,导致有效条目被过早清除。这会导致频繁进行 ARP 查找,造成网络延迟和延迟增加,尤其是在有多个活动设备的环境中。
  2. 过高(gc_thresh3 > 4096):ARP 缓存过度增长,占用的内存超出必要范围。在路由器等资源受限的设备上,这会导致内存分配效率低下,从而导致性能下降。
    选择正确的值取决于网络规模和设备容量。对于小型网络,平衡配置 (gc_thresh3 = 1024) 可确保最佳 ARP 解析,同时防止不必要的缓存驱逐。

探测前控制延迟
另一个有用的参数是 /proc/sys/net/ipv4/neigh/default/delay_first_probe_time,它控制内核发送 STALE 条目的第一个 ARP 探测之前的初始延迟时间。默认情况下,该时间设置为 5 秒,但调整它可以减少不必要的探测。延迟时间允许 ARP 条目自行返回到 REACHABLE 状态,从而最大限度地减少网络流量并提高系统整体性能。

几种场景:

  1. 过高(>10 秒):系统等待的时间过长,导致重新验证 ARP 条目,从而导致暂时的连接问题。这可能会导致与之前空闲的主机通信时出现数据包丢失或延迟,尤其是在 IP 地址频繁变化的动态网络中。
  2. 太低(少于 2 秒):ARP 探测发送过于频繁,导致网络流量和 CPU 使用率增加。在大型部署或繁忙的网络中,这可能会使系统不堪重负,从而产生不必要的处理开销。
    选择正确的值取决于网络稳定性和流量模式。对于大多数环境,默认的 5 秒可以达到良好的平衡,确保及时重新验证,而无需进行过多的 ARP 探测。

添加静态 ARP 条目

在某些情况下,您可能需要将静态 ARP 条目添加到缓存中。这些条目不会过期,也不会受到常规垃圾回收过程的影响。静态条目对于具有固定 IP 到 MAC 映射的设备(例如网络基础设施组件)非常有用。您可以使用 arp -s 或 ip neigh add 命令手动添加这些条目,以确保关键设备始终可访问,而无需重新解析其地址。

结论

虽然 ARP 是一个成熟且易于理解的协议,但它在网络中的作用依然至关重要。了解 ARP 的复杂性,包括它在 Linux 中的实现、高级功能以及潜在的安全隐患,可以帮助网络管理员和开发人员构建更安全、更高效的网络。

随着网络的不断发展,尤其是 IPv6(使用邻居发现协议而非 ARP)的出现,ARP 背后的原理对于未来的协议和实践仍然适用。然而,对于基于 IPv4 的网络,ARP 仍将发挥关键作用。

原文地址:https://blogs.oracle.com/linux/post/arp-internals
原文作者:Mohith Kumar Thummaluru

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论