第 6 篇:ARP 协议——IP 管远方,MAC 管眼前,它来搭桥

上一篇我们讲了 MAC 地址:IP 管远方,MAC 管眼前。今天继续追问一个更实际的问题:我知道对方 IP,怎么知道它的 MAC?这就轮到 ARP 出场了。


开场:我知道你住哪,但不知道你长啥样

上一篇我们说过一句很重要的话:

IP 管远方,MAC 管眼前。

但这里马上会冒出一个新问题。

假设你的电脑要访问同一局域网里的另一台机器:

text 复制代码
目标 IP:192.168.1.20

你的电脑知道目标 IP。

可是以太网真正发帧时,需要目标 MAC。

于是问题来了:

我知道你 IP 是多少,但我不知道你 MAC 是多少,这包怎么发?

这就像你知道同事坐在 8 楼工位,但不知道他长什么样。

你到了 8 楼之后,只能大喊一声:

谁是 192.168.1.20?出来认领一下!

这声大喊,就是 ARP。

准确地说,ARP 不是"帮我们找 IP"。

ARP 是:

已知 IP,寻找对应的 MAC 地址。

标题里说"谁在帮我们找 IP",主要是为了顺口。

技术上要严谨:

🔧 技术定义:ARP(Address Resolution Protocol,地址解析协议)负责根据 IP 地址解析出对应的 MAC 地址。

这句话后面还会反复出现。

因为它真的很重要。


🔧 先看一张总览图:ARP 在整个发送链路中的位置

#mermaid-svg-eGuv44fbic9YzL7g{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eGuv44fbic9YzL7g .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eGuv44fbic9YzL7g .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eGuv44fbic9YzL7g .error-icon{fill:#552222;}#mermaid-svg-eGuv44fbic9YzL7g .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eGuv44fbic9YzL7g .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eGuv44fbic9YzL7g .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eGuv44fbic9YzL7g .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eGuv44fbic9YzL7g .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eGuv44fbic9YzL7g .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eGuv44fbic9YzL7g .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eGuv44fbic9YzL7g .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eGuv44fbic9YzL7g .marker.cross{stroke:#333333;}#mermaid-svg-eGuv44fbic9YzL7g svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eGuv44fbic9YzL7g p{margin:0;}#mermaid-svg-eGuv44fbic9YzL7g .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eGuv44fbic9YzL7g .cluster-label text{fill:#333;}#mermaid-svg-eGuv44fbic9YzL7g .cluster-label span{color:#333;}#mermaid-svg-eGuv44fbic9YzL7g .cluster-label span p{background-color:transparent;}#mermaid-svg-eGuv44fbic9YzL7g .label text,#mermaid-svg-eGuv44fbic9YzL7g span{fill:#333;color:#333;}#mermaid-svg-eGuv44fbic9YzL7g .node rect,#mermaid-svg-eGuv44fbic9YzL7g .node circle,#mermaid-svg-eGuv44fbic9YzL7g .node ellipse,#mermaid-svg-eGuv44fbic9YzL7g .node polygon,#mermaid-svg-eGuv44fbic9YzL7g .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eGuv44fbic9YzL7g .rough-node .label text,#mermaid-svg-eGuv44fbic9YzL7g .node .label text,#mermaid-svg-eGuv44fbic9YzL7g .image-shape .label,#mermaid-svg-eGuv44fbic9YzL7g .icon-shape .label{text-anchor:middle;}#mermaid-svg-eGuv44fbic9YzL7g .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eGuv44fbic9YzL7g .rough-node .label,#mermaid-svg-eGuv44fbic9YzL7g .node .label,#mermaid-svg-eGuv44fbic9YzL7g .image-shape .label,#mermaid-svg-eGuv44fbic9YzL7g .icon-shape .label{text-align:center;}#mermaid-svg-eGuv44fbic9YzL7g .node.clickable{cursor:pointer;}#mermaid-svg-eGuv44fbic9YzL7g .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eGuv44fbic9YzL7g .arrowheadPath{fill:#333333;}#mermaid-svg-eGuv44fbic9YzL7g .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eGuv44fbic9YzL7g .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eGuv44fbic9YzL7g .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eGuv44fbic9YzL7g .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eGuv44fbic9YzL7g .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eGuv44fbic9YzL7g .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eGuv44fbic9YzL7g .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eGuv44fbic9YzL7g .cluster text{fill:#333;}#mermaid-svg-eGuv44fbic9YzL7g .cluster span{color:#333;}#mermaid-svg-eGuv44fbic9YzL7g div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eGuv44fbic9YzL7g .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eGuv44fbic9YzL7g rect.text{fill:none;stroke-width:0;}#mermaid-svg-eGuv44fbic9YzL7g .icon-shape,#mermaid-svg-eGuv44fbic9YzL7g .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eGuv44fbic9YzL7g .icon-shape p,#mermaid-svg-eGuv44fbic9YzL7g .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eGuv44fbic9YzL7g .icon-shape .label rect,#mermaid-svg-eGuv44fbic9YzL7g .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eGuv44fbic9YzL7g .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eGuv44fbic9YzL7g .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eGuv44fbic9YzL7g :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是


没有
应用要发送数据
操作系统知道目标 IP
目标和我同网段吗?
下一跳 = 目标主机
下一跳 = 网关
ARP 缓存里有下一跳 MAC 吗?
直接封装以太网帧发送
发送 ARP 广播请求
目标设备回复自己的 MAC
写入 ARP 缓存

这张图里有两个重点:

  1. ARP 找的是下一跳 MAC,不一定是最终目标 MAC。
  2. 下一跳可能是目标主机,也可能是网关。

如果目标在同一个局域网,ARP 找目标主机的 MAC。

如果目标不在同一个网段,ARP 找网关的 MAC。

这点不理解,后面抓包很容易怀疑人生。


ARP 到底怎么问?一个完整的请求-响应流程

我们先看最简单的场景。

主机 A 想访问主机 B。

text 复制代码
主机 A:192.168.1.10,MAC:AA:AA
主机 B:192.168.1.20,MAC:BB:BB

它们在同一个局域网。

主机 A 知道 B 的 IP,但不知道 B 的 MAC。

于是 A 会发一个 ARP 请求。

ARP 请求的内容:

text 复制代码
谁是 192.168.1.20?
请把你的 MAC 地址告诉 192.168.1.10(AA:AA)。

这个请求会以广播方式发出。

text 复制代码
目标 MAC:FF:FF:FF:FF:FF:FF

也就是发给当前局域网里的所有设备
其他主机 主机B\n192.168.1.20\nMAC: BB:BB 局域网(广播域) 主机A\n192.168.1.10\nMAC: AA:AA 其他主机 主机B\n192.168.1.20\nMAC: BB:BB 局域网(广播域) 主机A\n192.168.1.10\nMAC: AA:AA #mermaid-svg-oEoVLLrqfqxeWWjm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oEoVLLrqfqxeWWjm .error-icon{fill:#552222;}#mermaid-svg-oEoVLLrqfqxeWWjm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oEoVLLrqfqxeWWjm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oEoVLLrqfqxeWWjm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oEoVLLrqfqxeWWjm .marker.cross{stroke:#333333;}#mermaid-svg-oEoVLLrqfqxeWWjm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oEoVLLrqfqxeWWjm p{margin:0;}#mermaid-svg-oEoVLLrqfqxeWWjm .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-oEoVLLrqfqxeWWjm text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-oEoVLLrqfqxeWWjm .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-oEoVLLrqfqxeWWjm .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-oEoVLLrqfqxeWWjm #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-oEoVLLrqfqxeWWjm .sequenceNumber{fill:white;}#mermaid-svg-oEoVLLrqfqxeWWjm #sequencenumber{fill:#333;}#mermaid-svg-oEoVLLrqfqxeWWjm #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-oEoVLLrqfqxeWWjm .messageText{fill:#333;stroke:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-oEoVLLrqfqxeWWjm .labelText,#mermaid-svg-oEoVLLrqfqxeWWjm .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .loopText,#mermaid-svg-oEoVLLrqfqxeWWjm .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-oEoVLLrqfqxeWWjm .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-oEoVLLrqfqxeWWjm .noteText,#mermaid-svg-oEoVLLrqfqxeWWjm .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-oEoVLLrqfqxeWWjm .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-oEoVLLrqfqxeWWjm .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-oEoVLLrqfqxeWWjm .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-oEoVLLrqfqxeWWjm .actorPopupMenu{position:absolute;}#mermaid-svg-oEoVLLrqfqxeWWjm .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-oEoVLLrqfqxeWWjm .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-oEoVLLrqfqxeWWjm .actor-man circle,#mermaid-svg-oEoVLLrqfqxeWWjm line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-oEoVLLrqfqxeWWjm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ARP Request(广播):谁是 192.168.1.20?收到广播,IP 匹配收到广播,IP 不匹配,忽略ARP Reply(单播):我是,MAC 是 BB:BB写入 ARP 缓存

ARP 响应的内容:

text 复制代码
我就是 192.168.1.20
我的 MAC 是 BB:BB
你记一下

其他机器也会收到这个广播。

但它们一看:

问的不是我。

于是默默忽略。

这很像公司群里有人 @某个同事。所有人都看到了,但只有当事人回复。

当然,也不排除有人出来抢答。

网络里如果有人恶意抢答,那就是 ARP 欺骗

后面会讲。


🔧 ARP 报文长什么样?(可以拿去抓包对照)

ARP 报文大致包含这些信息:

字段 含义 ARP Request ARP Reply
发送方 MAC 谁在问/谁在答 AA:AA BB:BB
发送方 IP 谁在问/谁在答 192.168.1.10 192.168.1.20
目标 MAC 想找谁的 MAC 00:00:00:00:00:00(未知) AA:AA
目标 IP 想找哪个 IP 192.168.1.20 192.168.1.10
操作类型 请求还是响应 1(Request) 2(Reply)

用表格看更直观:

报文 发送方 IP 发送方 MAC 目标 IP 目标 MAC
ARP Request 192.168.1.10 AA:AA 192.168.1.20 00:00:00:00:00:00
ARP Reply 192.168.1.20 BB:BB 192.168.1.10 AA:AA

这里的逻辑很朴素。

朴素到有点像现实生活:

你是谁?

我是谁。

好,我记住你了。

网络协议有时候并没有想象中那么玄。

只是字段名比较严肃,让人看起来想关网页。


ARP 为什么必须用广播?

因为在发送 ARP 请求之前,主机正是不知道目标 MAC

如果已经知道目标 MAC,那就不需要 ARP 了。

所以它只能广播:

text 复制代码
目标 MAC:FF:FF:FF:FF:FF:FF
含义:局域网所有设备都听一下

这就像你到了一个陌生会议室,要找"张三"。

你不知道张三坐哪。

只能问一句:

哪位是张三?

如果你已经知道张三坐第三排靠窗,那你就不用问了。

直接过去就行。

ARP 广播也是这个逻辑。
#mermaid-svg-OS0TeLsuKM0xYhSu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OS0TeLsuKM0xYhSu .error-icon{fill:#552222;}#mermaid-svg-OS0TeLsuKM0xYhSu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OS0TeLsuKM0xYhSu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OS0TeLsuKM0xYhSu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OS0TeLsuKM0xYhSu .marker.cross{stroke:#333333;}#mermaid-svg-OS0TeLsuKM0xYhSu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OS0TeLsuKM0xYhSu p{margin:0;}#mermaid-svg-OS0TeLsuKM0xYhSu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu .cluster-label text{fill:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu .cluster-label span{color:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu .cluster-label span p{background-color:transparent;}#mermaid-svg-OS0TeLsuKM0xYhSu .label text,#mermaid-svg-OS0TeLsuKM0xYhSu span{fill:#333;color:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu .node rect,#mermaid-svg-OS0TeLsuKM0xYhSu .node circle,#mermaid-svg-OS0TeLsuKM0xYhSu .node ellipse,#mermaid-svg-OS0TeLsuKM0xYhSu .node polygon,#mermaid-svg-OS0TeLsuKM0xYhSu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OS0TeLsuKM0xYhSu .rough-node .label text,#mermaid-svg-OS0TeLsuKM0xYhSu .node .label text,#mermaid-svg-OS0TeLsuKM0xYhSu .image-shape .label,#mermaid-svg-OS0TeLsuKM0xYhSu .icon-shape .label{text-anchor:middle;}#mermaid-svg-OS0TeLsuKM0xYhSu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OS0TeLsuKM0xYhSu .rough-node .label,#mermaid-svg-OS0TeLsuKM0xYhSu .node .label,#mermaid-svg-OS0TeLsuKM0xYhSu .image-shape .label,#mermaid-svg-OS0TeLsuKM0xYhSu .icon-shape .label{text-align:center;}#mermaid-svg-OS0TeLsuKM0xYhSu .node.clickable{cursor:pointer;}#mermaid-svg-OS0TeLsuKM0xYhSu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OS0TeLsuKM0xYhSu .arrowheadPath{fill:#333333;}#mermaid-svg-OS0TeLsuKM0xYhSu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OS0TeLsuKM0xYhSu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OS0TeLsuKM0xYhSu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OS0TeLsuKM0xYhSu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OS0TeLsuKM0xYhSu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OS0TeLsuKM0xYhSu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OS0TeLsuKM0xYhSu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OS0TeLsuKM0xYhSu .cluster text{fill:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu .cluster span{color:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OS0TeLsuKM0xYhSu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OS0TeLsuKM0xYhSu rect.text{fill:none;stroke-width:0;}#mermaid-svg-OS0TeLsuKM0xYhSu .icon-shape,#mermaid-svg-OS0TeLsuKM0xYhSu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OS0TeLsuKM0xYhSu .icon-shape p,#mermaid-svg-OS0TeLsuKM0xYhSu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OS0TeLsuKM0xYhSu .icon-shape .label rect,#mermaid-svg-OS0TeLsuKM0xYhSu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OS0TeLsuKM0xYhSu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OS0TeLsuKM0xYhSu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OS0TeLsuKM0xYhSu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不知道目标 MAC
只能广播询问
目标主机响应
记录到 ARP 缓存
下次直接单播发送

⚠️ 广播的代价:广播虽然方便,但不能滥用。因为广播会打扰同一局域网里的所有设备。一次两次没事,太多了就会影响网络。就像公司群里偶尔 @所有人 可以,天天 @所有人,大家就想把你静音。


ARP 缓存:别每次都满楼喊人

如果每发送一个包都广播问一次 MAC,那局域网会很吵。

所以操作系统会维护 ARP 缓存

也就是:

text 复制代码
IP 地址  ->  MAC 地址

比如:

text 复制代码
192.168.1.1   ->  00:11:22:33:44:55
192.168.1.20  ->  aa:bb:cc:dd:ee:ff

下次再发包时,先查缓存。

有就直接用。

没有再广播问。

在 Linux 上查看 ARP 缓存:

bash 复制代码
ip neigh

可能看到类似:

text 复制代码
192.168.1.1 dev eth0 lladdr 00:11:22:33:44:55 REACHABLE
192.168.1.20 dev eth0 lladdr aa:bb:cc:dd:ee:ff STALE

这里的 lladdr 就是链路层地址,也就是 MAC。

状态含义:

状态 大致含义
REACHABLE 最近确认可达
STALE 缓存有点旧,必要时重新确认
DELAY 等待确认
PROBE 正在探测
FAILED 解析失败

手动管理 ARP 缓存:

bash 复制代码
# 添加静态 ARP 条目
ip neigh add 192.168.1.100 lladdr 00:11:22:33:44:55 dev eth0

# 删除某个条目
ip neigh del 192.168.1.100 dev eth0

# 清空所有缓存
ip neigh flush all

⚠️ 注意:ARP 缓存就是为了减少重复广播。有缓存,效率高。没缓存,就先问。缓存错了,就开始出怪问题。缓存这东西,哪都一样,用得好是优化,脏了就是事故。


同网段通信:ARP 找目标主机的 MAC

同网段通信时,ARP 要找的是目标主机的 MAC

比如:

text 复制代码
主机 A:192.168.1.10/24,MAC:AA:AA
主机 B:192.168.1.20/24,MAC:BB:BB

A 发现 B 和自己在同一个网段,于是直接找 B 的 MAC。
#mermaid-svg-xx9hpk76u6pHLsyY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xx9hpk76u6pHLsyY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xx9hpk76u6pHLsyY .error-icon{fill:#552222;}#mermaid-svg-xx9hpk76u6pHLsyY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xx9hpk76u6pHLsyY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xx9hpk76u6pHLsyY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xx9hpk76u6pHLsyY .marker.cross{stroke:#333333;}#mermaid-svg-xx9hpk76u6pHLsyY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xx9hpk76u6pHLsyY p{margin:0;}#mermaid-svg-xx9hpk76u6pHLsyY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xx9hpk76u6pHLsyY .cluster-label text{fill:#333;}#mermaid-svg-xx9hpk76u6pHLsyY .cluster-label span{color:#333;}#mermaid-svg-xx9hpk76u6pHLsyY .cluster-label span p{background-color:transparent;}#mermaid-svg-xx9hpk76u6pHLsyY .label text,#mermaid-svg-xx9hpk76u6pHLsyY span{fill:#333;color:#333;}#mermaid-svg-xx9hpk76u6pHLsyY .node rect,#mermaid-svg-xx9hpk76u6pHLsyY .node circle,#mermaid-svg-xx9hpk76u6pHLsyY .node ellipse,#mermaid-svg-xx9hpk76u6pHLsyY .node polygon,#mermaid-svg-xx9hpk76u6pHLsyY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xx9hpk76u6pHLsyY .rough-node .label text,#mermaid-svg-xx9hpk76u6pHLsyY .node .label text,#mermaid-svg-xx9hpk76u6pHLsyY .image-shape .label,#mermaid-svg-xx9hpk76u6pHLsyY .icon-shape .label{text-anchor:middle;}#mermaid-svg-xx9hpk76u6pHLsyY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xx9hpk76u6pHLsyY .rough-node .label,#mermaid-svg-xx9hpk76u6pHLsyY .node .label,#mermaid-svg-xx9hpk76u6pHLsyY .image-shape .label,#mermaid-svg-xx9hpk76u6pHLsyY .icon-shape .label{text-align:center;}#mermaid-svg-xx9hpk76u6pHLsyY .node.clickable{cursor:pointer;}#mermaid-svg-xx9hpk76u6pHLsyY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xx9hpk76u6pHLsyY .arrowheadPath{fill:#333333;}#mermaid-svg-xx9hpk76u6pHLsyY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xx9hpk76u6pHLsyY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xx9hpk76u6pHLsyY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xx9hpk76u6pHLsyY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xx9hpk76u6pHLsyY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xx9hpk76u6pHLsyY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xx9hpk76u6pHLsyY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xx9hpk76u6pHLsyY .cluster text{fill:#333;}#mermaid-svg-xx9hpk76u6pHLsyY .cluster span{color:#333;}#mermaid-svg-xx9hpk76u6pHLsyY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xx9hpk76u6pHLsyY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xx9hpk76u6pHLsyY rect.text{fill:none;stroke-width:0;}#mermaid-svg-xx9hpk76u6pHLsyY .icon-shape,#mermaid-svg-xx9hpk76u6pHLsyY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xx9hpk76u6pHLsyY .icon-shape p,#mermaid-svg-xx9hpk76u6pHLsyY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xx9hpk76u6pHLsyY .icon-shape .label rect,#mermaid-svg-xx9hpk76u6pHLsyY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xx9hpk76u6pHLsyY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xx9hpk76u6pHLsyY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xx9hpk76u6pHLsyY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 主机A

192.168.1.10

MAC AA:AA
ARP广播

谁是 192.168.1.20?
主机B

192.168.1.20

MAC BB:BB
ARP响应

我是,MAC 是 BB:BB
以太网帧

目标MAC=BB:BB

目标IP=192.168.1.20

最终发出的以太网帧:

text 复制代码
源 MAC:AA:AA
目标 MAC:BB:BB
源 IP:192.168.1.10
目标 IP:192.168.1.20

这比较直观。

同一个局域网里,直接找对方。

像在同一层办公室找人。知道工位后就直接过去。


跨网段通信:ARP 找网关的 MAC

跨网段就不一样了。

比如你的电脑要访问公网服务器:

text 复制代码
你的电脑:192.168.1.10/24,MAC:AA:AA
网关:192.168.1.1,MAC:GG:GG
目标服务器:93.184.216.34

你的电脑会先判断:

93.184.216.34 和我不在同一个网段。

那就不能直接发给目标服务器。

要先交给网关。

于是 ARP 找的是网关的 MAC
#mermaid-svg-gPOJOGHLhNSh8ZcJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .error-icon{fill:#552222;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .marker.cross{stroke:#333333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ p{margin:0;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .cluster-label text{fill:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .cluster-label span{color:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .cluster-label span p{background-color:transparent;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .label text,#mermaid-svg-gPOJOGHLhNSh8ZcJ span{fill:#333;color:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .node rect,#mermaid-svg-gPOJOGHLhNSh8ZcJ .node circle,#mermaid-svg-gPOJOGHLhNSh8ZcJ .node ellipse,#mermaid-svg-gPOJOGHLhNSh8ZcJ .node polygon,#mermaid-svg-gPOJOGHLhNSh8ZcJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .rough-node .label text,#mermaid-svg-gPOJOGHLhNSh8ZcJ .node .label text,#mermaid-svg-gPOJOGHLhNSh8ZcJ .image-shape .label,#mermaid-svg-gPOJOGHLhNSh8ZcJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .rough-node .label,#mermaid-svg-gPOJOGHLhNSh8ZcJ .node .label,#mermaid-svg-gPOJOGHLhNSh8ZcJ .image-shape .label,#mermaid-svg-gPOJOGHLhNSh8ZcJ .icon-shape .label{text-align:center;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .node.clickable{cursor:pointer;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .arrowheadPath{fill:#333333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gPOJOGHLhNSh8ZcJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gPOJOGHLhNSh8ZcJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gPOJOGHLhNSh8ZcJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .cluster text{fill:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .cluster span{color:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gPOJOGHLhNSh8ZcJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .icon-shape,#mermaid-svg-gPOJOGHLhNSh8ZcJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .icon-shape p,#mermaid-svg-gPOJOGHLhNSh8ZcJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .icon-shape .label rect,#mermaid-svg-gPOJOGHLhNSh8ZcJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gPOJOGHLhNSh8ZcJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gPOJOGHLhNSh8ZcJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gPOJOGHLhNSh8ZcJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 你的电脑

192.168.1.10
ARP广播

谁是 192.168.1.1?
网关

192.168.1.1

MAC GG:GG
ARP响应

我是网关,MAC 是 GG:GG
发以太网帧

目标MAC=GG:GG

目标IP=93.184.216.34
继续路由到互联网

最终第一跳帧里是:

text 复制代码
源 MAC:你的电脑 MAC(AA:AA)
目标 MAC:网关 MAC(GG:GG)
源 IP:192.168.1.10
目标 IP:93.184.216.34

这就是上一篇反复讲的:IP 管远方,MAC 管眼前

目标 IP 是远方。

目标 MAC 是眼前的网关。

如果你抓包看到这种情况,不要紧张。不是包迷路了。它只是先去找导航员。


🔧 ARP 和路由表是什么关系?(很多人搞混)

ARP 不是自己决定走哪条路。

谁决定下一跳?路由表。

ARP 只负责把下一跳 IP 解析成 MAC。

流程大概是:
#mermaid-svg-pow8tQIm1D4bZHVy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pow8tQIm1D4bZHVy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pow8tQIm1D4bZHVy .error-icon{fill:#552222;}#mermaid-svg-pow8tQIm1D4bZHVy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pow8tQIm1D4bZHVy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pow8tQIm1D4bZHVy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pow8tQIm1D4bZHVy .marker.cross{stroke:#333333;}#mermaid-svg-pow8tQIm1D4bZHVy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pow8tQIm1D4bZHVy p{margin:0;}#mermaid-svg-pow8tQIm1D4bZHVy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pow8tQIm1D4bZHVy .cluster-label text{fill:#333;}#mermaid-svg-pow8tQIm1D4bZHVy .cluster-label span{color:#333;}#mermaid-svg-pow8tQIm1D4bZHVy .cluster-label span p{background-color:transparent;}#mermaid-svg-pow8tQIm1D4bZHVy .label text,#mermaid-svg-pow8tQIm1D4bZHVy span{fill:#333;color:#333;}#mermaid-svg-pow8tQIm1D4bZHVy .node rect,#mermaid-svg-pow8tQIm1D4bZHVy .node circle,#mermaid-svg-pow8tQIm1D4bZHVy .node ellipse,#mermaid-svg-pow8tQIm1D4bZHVy .node polygon,#mermaid-svg-pow8tQIm1D4bZHVy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pow8tQIm1D4bZHVy .rough-node .label text,#mermaid-svg-pow8tQIm1D4bZHVy .node .label text,#mermaid-svg-pow8tQIm1D4bZHVy .image-shape .label,#mermaid-svg-pow8tQIm1D4bZHVy .icon-shape .label{text-anchor:middle;}#mermaid-svg-pow8tQIm1D4bZHVy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pow8tQIm1D4bZHVy .rough-node .label,#mermaid-svg-pow8tQIm1D4bZHVy .node .label,#mermaid-svg-pow8tQIm1D4bZHVy .image-shape .label,#mermaid-svg-pow8tQIm1D4bZHVy .icon-shape .label{text-align:center;}#mermaid-svg-pow8tQIm1D4bZHVy .node.clickable{cursor:pointer;}#mermaid-svg-pow8tQIm1D4bZHVy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pow8tQIm1D4bZHVy .arrowheadPath{fill:#333333;}#mermaid-svg-pow8tQIm1D4bZHVy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pow8tQIm1D4bZHVy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pow8tQIm1D4bZHVy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pow8tQIm1D4bZHVy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pow8tQIm1D4bZHVy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pow8tQIm1D4bZHVy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pow8tQIm1D4bZHVy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pow8tQIm1D4bZHVy .cluster text{fill:#333;}#mermaid-svg-pow8tQIm1D4bZHVy .cluster span{color:#333;}#mermaid-svg-pow8tQIm1D4bZHVy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pow8tQIm1D4bZHVy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pow8tQIm1D4bZHVy rect.text{fill:none;stroke-width:0;}#mermaid-svg-pow8tQIm1D4bZHVy .icon-shape,#mermaid-svg-pow8tQIm1D4bZHVy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pow8tQIm1D4bZHVy .icon-shape p,#mermaid-svg-pow8tQIm1D4bZHVy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pow8tQIm1D4bZHVy .icon-shape .label rect,#mermaid-svg-pow8tQIm1D4bZHVy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pow8tQIm1D4bZHVy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pow8tQIm1D4bZHVy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pow8tQIm1D4bZHVy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

准备发送 IP 包
查路由表
目标是否同网段?
下一跳 = 目标 IP
下一跳 = 网关 IP
ARP 解析下一跳 MAC
封装以太网帧
发送

这就是 ARP 在整个发送链路中的位置。

路由表先决定下一跳是谁。

ARP 再问下一跳的 MAC 是多少。

所以别把路由和 ARP 混在一起。

它们是合作关系。

角色 做什么 类比
路由表 决定下一跳 IP 导航软件告诉你下一站去哪
ARP 把下一跳 IP 解析成 MAC 前台告诉你这个人长什么样

🔧 抓包看 ARP(手把手)

ARP 很适合抓包观察。

在 Linux 上抓 ARP 包:

bash 复制代码
sudo tcpdump -i eth0 arp -n

你可能会看到类似输出:

text 复制代码
ARP, Request who-has 192.168.1.1 tell 192.168.1.10
ARP, Reply 192.168.1.1 is-at 00:11:22:33:44:55

翻译成人话就是:

text 复制代码
192.168.1.10:谁是 192.168.1.1?
192.168.1.1:我是,我的 MAC 是 00:11:22:33:44:55。

主动触发 ARP:

如果你想触发 ARP,可以先清一下邻居缓存,再 ping 一下网关。

bash 复制代码
# 清空 ARP 缓存
sudo ip neigh flush all

# ping 网关(会触发 ARP)
ping 192.168.1.1

然后抓包看 ARP 请求和响应。

⚠️ 生产环境不要随便清 ARP 缓存。学习环境可以玩,线上环境玩这个,值班群可能也会开始玩你。


ARP 出问题会怎样?(现象清单)

ARP 很基础。

基础到平时没感觉。

一旦出问题,就很明显。

常见表现:

  • 同网段机器互相 ping 不通
  • 能看到 IP,但无法通信
  • 网关 MAC 解析失败
  • 访问外网失败
  • 网络时通时断
  • ARP 表里 MAC 不对
  • IP 冲突导致 ARP 抖动

示例:

bash 复制代码
ip neigh

看到:

text 复制代码
192.168.1.1 dev eth0 FAILED

这说明系统尝试解析网关 MAC 失败。

如果网关 MAC 都找不到,后面访问外网基本就没戏。

这时候你继续 curl 某个网站,很可能只是得到一个失败结果。

不是 HTTP 不努力。是包还没出小区。


ARP 欺骗:有人冒充网关(安全视角)

ARP 有一个设计上的弱点:

它太相信别人了。

ARP Reply 基本是在说:

text 复制代码
我是 192.168.1.1,我的 MAC 是 XX:XX。

问题是,如果有坏人也这么说呢?

比如攻击者对局域网里的主机说:

text 复制代码
我是网关 192.168.1.1,我的 MAC 是攻击者 MAC。

如果主机信了,它就会把发往网关的流量交给攻击者。

这就是 ARP 欺骗 的一种典型思路。
#mermaid-svg-H7NrZI2dwgGUWOzi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-H7NrZI2dwgGUWOzi .error-icon{fill:#552222;}#mermaid-svg-H7NrZI2dwgGUWOzi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-H7NrZI2dwgGUWOzi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-H7NrZI2dwgGUWOzi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-H7NrZI2dwgGUWOzi .marker.cross{stroke:#333333;}#mermaid-svg-H7NrZI2dwgGUWOzi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-H7NrZI2dwgGUWOzi p{margin:0;}#mermaid-svg-H7NrZI2dwgGUWOzi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi .cluster-label text{fill:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi .cluster-label span{color:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi .cluster-label span p{background-color:transparent;}#mermaid-svg-H7NrZI2dwgGUWOzi .label text,#mermaid-svg-H7NrZI2dwgGUWOzi span{fill:#333;color:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi .node rect,#mermaid-svg-H7NrZI2dwgGUWOzi .node circle,#mermaid-svg-H7NrZI2dwgGUWOzi .node ellipse,#mermaid-svg-H7NrZI2dwgGUWOzi .node polygon,#mermaid-svg-H7NrZI2dwgGUWOzi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-H7NrZI2dwgGUWOzi .rough-node .label text,#mermaid-svg-H7NrZI2dwgGUWOzi .node .label text,#mermaid-svg-H7NrZI2dwgGUWOzi .image-shape .label,#mermaid-svg-H7NrZI2dwgGUWOzi .icon-shape .label{text-anchor:middle;}#mermaid-svg-H7NrZI2dwgGUWOzi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-H7NrZI2dwgGUWOzi .rough-node .label,#mermaid-svg-H7NrZI2dwgGUWOzi .node .label,#mermaid-svg-H7NrZI2dwgGUWOzi .image-shape .label,#mermaid-svg-H7NrZI2dwgGUWOzi .icon-shape .label{text-align:center;}#mermaid-svg-H7NrZI2dwgGUWOzi .node.clickable{cursor:pointer;}#mermaid-svg-H7NrZI2dwgGUWOzi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-H7NrZI2dwgGUWOzi .arrowheadPath{fill:#333333;}#mermaid-svg-H7NrZI2dwgGUWOzi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-H7NrZI2dwgGUWOzi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-H7NrZI2dwgGUWOzi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H7NrZI2dwgGUWOzi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-H7NrZI2dwgGUWOzi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H7NrZI2dwgGUWOzi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-H7NrZI2dwgGUWOzi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-H7NrZI2dwgGUWOzi .cluster text{fill:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi .cluster span{color:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-H7NrZI2dwgGUWOzi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-H7NrZI2dwgGUWOzi rect.text{fill:none;stroke-width:0;}#mermaid-svg-H7NrZI2dwgGUWOzi .icon-shape,#mermaid-svg-H7NrZI2dwgGUWOzi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H7NrZI2dwgGUWOzi .icon-shape p,#mermaid-svg-H7NrZI2dwgGUWOzi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-H7NrZI2dwgGUWOzi .icon-shape .label rect,#mermaid-svg-H7NrZI2dwgGUWOzi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H7NrZI2dwgGUWOzi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-H7NrZI2dwgGUWOzi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-H7NrZI2dwgGUWOzi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 以为目标MAC是攻击者
正常主机
攻击者

伪装成网关
真正网关

防护思路:

  • 静态 ARP 绑定
  • 交换机 ARP 防护(DAI,Dynamic ARP Inspection)
  • DHCP Snooping
  • 网络隔离(VLAN)

重点是理解:ARP 工作在局域网内,且缺少强认证,所以它既基础,也容易被滥用。

网络协议很多都诞生在一个相对单纯的年代。

后来互联网长大了。

坏人也长大了。

协议就开始显得有点天真。


🧠 工程排查:遇到网络不通,什么时候该看 ARP?

如果你遇到下面这些情况,应该想到 ARP:

1. 同网段不通

比如:

bash 复制代码
ping 192.168.1.20

不通。

先看:

bash 复制代码
ip neigh show 192.168.1.20

如果是 FAILED,说明 MAC 没解析出来。

2. 外网不通,但本机 IP 正常

先看网关:

bash 复制代码
ip route
ip neigh show 网关IP

如果网关 MAC 解析失败,问题可能在链路、网关、VLAN、交换机或 ARP。

3. 网络时通时断

看 ARP 表是否频繁变化。

如果同一个 IP 对应的 MAC 来回跳,可能有:

  • IP 冲突
  • ARP 欺骗
  • 虚拟化网络异常
  • 网关漂移配置问题
4. 抓包看到大量 ARP

大量 ARP 可能说明:

  • 缓存频繁失效
  • 有主机频繁探测
  • 网络配置异常
  • 存在扫描或攻击行为

排查命令速查表:

命令 作用
ip neigh 查看 ARP 缓存
ip route 查看路由表
sudo tcpdump -i eth0 arp 抓 ARP 包
arping 192.168.1.1 主动发 ARP 请求

arping 比 ping 更贴近链路层问题,很好用。


常见误区

误区一:ARP 是根据 MAC 找 IP

不对。

ARP 是已知 IP,找 MAC

反过来根据 MAC 找 IP(RARP)是另一个协议,现在已经很少用了。

别记反。记反了,后面看抓包会像把地图倒过来看。也能看,但容易走沟里。

误区二:访问公网服务器时,ARP 会找服务器 MAC

不对。

如果目标不在同一个二层网络,ARP 找的是网关 MAC

公网服务器的 MAC 不会直接出现在你本机发出的第一跳以太网帧里。

除非它和你在同一个二层网络------这在访问公网网站时通常不成立。

误区三:ARP 只发生一次

不对。

ARP 缓存会过期。

网络状态会变化。

设备会上下线。

MAC 可能会变化。

所以 ARP 会反复发生,只是有缓存时不需要每次都广播。

误区四:ping 不通一定是 ARP 问题

不一定。

ping 不通可能发生在很多层:

  • 物理链路问题
  • ARP 解析失败
  • IP 路由问题
  • 防火墙拦截 ICMP
  • 对方禁 ping
  • 回程路由异常

ARP 是候选项之一,不是万能背锅侠。别什么都甩给它。ARP 已经很辛苦了。


小结

这一篇我们讲了 ARP。

核心知识点:

  1. ARP 的作用是 已知 IP,寻找 MAC
  2. ARP 找的是下一跳 MAC,不一定是最终目标 MAC。
  3. 同网段通信时,ARP 找目标主机 MAC。
  4. 跨网段通信时,ARP 找网关 MAC。
  5. ARP 请求通常是广播,ARP 响应通常是单播。
  6. ARP 缓存用于避免每次通信都广播。
  7. ARP 出问题会导致同网段通信、网关访问、外网访问异常。
  8. ARP 缺少强认证,所以存在 ARP 欺骗风险。

一句话总结:

路由表决定下一跳是谁,ARP 负责问出下一跳的 MAC。

和上一篇连起来背:

IP 管远方,MAC 管眼前;路由定方向,ARP 找 MAC。


下一篇预告

下一篇我们继续讲数据链路层里的另一个关键角色:

第 7 篇:交换机------智能的"邮递员"

ARP 解决了"IP 对应哪个 MAC"。

那交换机拿到目标 MAC 之后,又是怎么知道该从哪个端口发出去的?

它怎么学习 MAC 地址?

找不到目标 MAC 时为什么要泛洪?

下一篇,我们继续拆交换机。


相关推荐
国科安芯1 小时前
商业航天级抗辐照全双工RS-485/RS-422收发器ASM491S2Y的技术特性与应用研究
运维·网络·单片机·嵌入式硬件·安全·架构·安全性测试
酣大智1 小时前
BGP选路原则--Med(6)
运维·网络·路由器·bgp
weixin_408318041 小时前
直播延迟优化实战:从1秒到200ms,WebRTC在医疗直播中的极致优化
服务器·网络·webrtc
探客木木夕1 小时前
分布式全球类脑智能网络架构设计
网络·人工智能·分布式·边缘计算
xxlyss&w1 小时前
Tenda AC9 V15.03.05.19(6318)_CN FUN_000384c8 — HTTP CGI 命令注入漏洞分析
网络·网络协议·http
dualven_in_csdn2 小时前
Vue3 SPA 支持 SEO 终极总结
网络
开开心心就好2 小时前
新手友好的音视频格式转换工具
linux·服务器·网络·智能手机·pdf·beautifulsoup·音视频
xlq223222 小时前
65.tcp—done
服务器·网络协议·tcp/ip
Zella折耳根2 小时前
Java 正则表达式实战:IP 地址匹配与替换全解析
java·tcp/ip·正则表达式