上一篇我们讲了 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 缓存
这张图里有两个重点:
- ARP 找的是下一跳 MAC,不一定是最终目标 MAC。
- 下一跳可能是目标主机,也可能是网关。
如果目标在同一个局域网,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。
核心知识点:
- ARP 的作用是 已知 IP,寻找 MAC。
- ARP 找的是下一跳 MAC,不一定是最终目标 MAC。
- 同网段通信时,ARP 找目标主机 MAC。
- 跨网段通信时,ARP 找网关 MAC。
- ARP 请求通常是广播,ARP 响应通常是单播。
- ARP 缓存用于避免每次通信都广播。
- ARP 出问题会导致同网段通信、网关访问、外网访问异常。
- ARP 缺少强认证,所以存在 ARP 欺骗风险。
一句话总结:
路由表决定下一跳是谁,ARP 负责问出下一跳的 MAC。
和上一篇连起来背:
IP 管远方,MAC 管眼前;路由定方向,ARP 找 MAC。
下一篇预告
下一篇我们继续讲数据链路层里的另一个关键角色:
第 7 篇:交换机------智能的"邮递员"
ARP 解决了"IP 对应哪个 MAC"。
那交换机拿到目标 MAC 之后,又是怎么知道该从哪个端口发出去的?
它怎么学习 MAC 地址?
找不到目标 MAC 时为什么要泛洪?
下一篇,我们继续拆交换机。