176 lines
7.0 KiB
Markdown
176 lines
7.0 KiB
Markdown
---
|
||
tags: [计算机网络, ARP, gratuitous-ARP, ARP欺骗]
|
||
create time: 2026-05-18 00:40
|
||
---
|
||
|
||
# ARP 协议完整流程
|
||
|
||
## 概述
|
||
|
||
ARP(Address Resolution Protocol,地址解析协议)负责将 IP 地址解析为同一局域网内的 MAC 地址。它是 IPv4 网络通信中不可或缺的"胶水协议"——每对首次通信的主机之间都必须经过一次 ARP。
|
||
|
||
## ARP 报文格式
|
||
|
||
ARP 直接封装在 Ethernet 帧中(EtherType = 0x0806),不依赖 IP:
|
||
|
||
```
|
||
┌───────────────────┬───────────────┬────────────────────┐
|
||
│ Hardware Type │ Protocol Type │ Hardware Addr Len │
|
||
│ 2 bytes │ 2 bytes │ 1 byte │
|
||
│ 1 = Ethernet │ 0x0800=IP │ always 6 │
|
||
├───────────────────┼───────────────┼────────────────────┤
|
||
│ Protocol Addr Len │ Operation │ Sender MAC │
|
||
│ 1 byte │ 2 bytes │ 6 bytes │
|
||
│ always 4 │ 1=Request │ │
|
||
│ │ 2=Reply │ │
|
||
├───────────────────┴───────────────┴────────────────────┤
|
||
│ Sender IP Address (4 bytes) │
|
||
├────────────────────────────────────────────────────────┤
|
||
│ Target IP Address (4 bytes) │
|
||
├────────────────────────────────────────────────────────┤
|
||
│ Target MAC Address (6 bytes) │
|
||
│ (in Request, this is zeroed/empty) │
|
||
└────────────────────────────────────────────────────────┘
|
||
Total: 28 bytes payload (padded to ≥ 46 bytes by Ethernet)
|
||
```
|
||
|
||
### Operation 字段
|
||
|
||
| 值 | 含义 |
|
||
|----|------|
|
||
| 1 | **ARP Request** — "谁是 x.x.x.x?请告诉我的 MAC" |
|
||
| 2 | **ARP Reply** — "我是 x.x.x.x,我的 MAC 是 yy" |
|
||
| 3 | RARP (Reverse ARP) — 历史遗留,已废弃 |
|
||
| 8 | InARP (Inverse ARP) — ATM 网络用 |
|
||
|
||
## ARP 请求与回复流程
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Src as PC-A<br/>192.168.1.10/aa:bb:cc:dd:ee:01
|
||
participant Bcast as 广播域内所有主机
|
||
participant Dst as PC-B<br/>192.168.1.20/?mac
|
||
|
||
Note over Src: Application wants to send packet to .20<br/>But needs MAC first!
|
||
|
||
Src->>Bcast: ARP Request (Broadcast)<br/>Who has 192.168.1.20? Tell 192.168.1.10
|
||
Note over Src,Bcast: Src MAC=aa:bb:cc:dd:ee:01<br/>Dst MAC=ff:ff:ff:ff:ff:ff<br/>Target IP=.20, Target MAC=00:00:00:00:00:00
|
||
|
||
loop For each host on LAN
|
||
Bcast-->>Host-C: 收到但不匹配 → 忽略
|
||
end
|
||
|
||
Dst-->>Src: ARP Reply (Unicast)<br/>192.168.1.20 is at aa:bb:cc:dd:ee:20
|
||
|
||
Src->>Src: Update ARP Cache: 192.168.1.20 → aa:bb:cc:dd:ee:20
|
||
```
|
||
|
||
### ARP 缓存条目
|
||
|
||
```bash
|
||
$ ip neigh show
|
||
192.168.1.20 dev eth0 lladdr aa:bb:cc:dd:ee:20 STALE
|
||
192.168.1.1 dev eth0 lladdr aa:bb:cc:dd:ee:01 REACHABLE
|
||
fe80::1 dev eth0 lladdr aa:bb:cc:dd:ee:01 DELAY
|
||
|
||
# 状态机:
|
||
# INCOMPLETE — 请求已发但未收到回复
|
||
# REACHABLE — 确认可达(刚收到回复或收到 ACK)
|
||
# STALE — 过期但可用,等待下次验证
|
||
# DELAY — 已标记为 STALE,等待 probe
|
||
# FAILED — Probe 全部失败
|
||
```
|
||
|
||
### ARP 缓存超时时间
|
||
|
||
```bash
|
||
# Linux 默认超时(秒)
|
||
$ sysctl net.ipv4.neigh.default.base_reachable_time_ms
|
||
net.ipv4.neigh.default.base_reachable_time_ms = 30000 # 30s
|
||
|
||
# 可调为毫秒精度
|
||
$ echo 60000 > /proc/sys/net/ipv4/neigh/default/base_reachable_time_ms # 改为 60s
|
||
```
|
||
|
||
## Gratuitous ARP(免费 ARP / 主动 ARP)
|
||
|
||
### 什么是 Gratuitous ARP?
|
||
|
||
一台主机**主动发送 ARP 回复**,即使没有收到任何请求。这相当于在广播域中宣布:"我现在是 xx:xx:xx:xx:xx:xx,绑定的是 x.x.x.x"。
|
||
|
||
### 三种使用场景
|
||
|
||
| 场景 | 目的 |
|
||
|------|------|
|
||
| 网卡故障切换 (VRRP/Keepalived) | 通知交换机更新 MAC→端口映射 |
|
||
| IP 冲突检测 | 先发送 GARP,如果有人回应则发现冲突 |
|
||
| 虚拟机迁移 | 新宿主机的 MAC 替代旧主机的 IP |
|
||
| DHCP 续租 | 重新声明自己的地址绑定关系 |
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant V1 as VM-on-Host-A<br/>IP: 10.0.0.10<br/>MAC: aa:bb:cc:00:00:01
|
||
participant SW as Switch
|
||
participant Migrate as VM migrates to Host-B
|
||
|
||
Note over V1: Live Migration starts...
|
||
V1->>SW: 最后一帧 from Host-A<br/>Switch learns: .10 → Port-X
|
||
|
||
Note over Migrate: VM boots on Host-B<br/>Same IP, New MAC!
|
||
Migrate->>SW: GARP "10.0.0.10 is now cc:dd:ee:00:00:01!"
|
||
SW->>SW: UPDATE MAC table:<br/>.10 → Port-Y ✅
|
||
|
||
Note over V1,Migrate: Without GARP, all traffic would go to old port 😱
|
||
```
|
||
|
||
## ARP 安全与攻击
|
||
|
||
### ARP Spoofing / Poisoning
|
||
|
||
攻击者发送伪造的 ARP Reply,让受害者认为网关的 MAC 已被篡改:
|
||
|
||
```
|
||
Before:
|
||
PC: "Gateway is at aa:bb:cc:gg:hh:ii ✅"
|
||
Server: "I am at dd:ee:ff:jj:kk:ll ✅"
|
||
|
||
After Attack (Attacker injects fake ARP):
|
||
PC: "Gateway is at mm:nn:oo:pp:qq:rr ❌ ← Attacker's MAC!"
|
||
```
|
||
|
||
### 防范措施
|
||
|
||
| 措施 | 说明 | 部署位置 |
|
||
|------|------|---------|
|
||
| **静态 ARP** | `arp -s` 手动绑定 | 小型网络,管理成本高 |
|
||
| **Dynamic ARP Inspection (DAI)** | Switch 拦截非合法 DHCP binding 的 ARP | 交换机配置 |
|
||
| **ARP Watch / Arpmonitor** | 监控 ARP 变动并告警 | 服务端 |
|
||
| **ndp-scan / arp-scan** | 定期扫描 ARP 表变化 | 运维工具 |
|
||
|
||
```bash
|
||
# 手动添加静态 ARP 条目(重启失效)
|
||
$ sudo ip neigh add 192.168.1.1 lladdr aa:bb:cc:dd:ee:01 nud permanent dev eth0
|
||
|
||
# 永久生效需写入 NetworkManager 或 systemd-networkd 配置
|
||
```
|
||
|
||
## IPv6 中的替代:NDP(Neighbor Discovery Protocol)
|
||
|
||
IPv6 废除了 ARP,改用 NDP(ICMPv6 类型 133/134/135/136):
|
||
|
||
| ARP 功能 | NDP 实现 | ICMPv6 Type |
|
||
|----------|---------|-------------|
|
||
| ARP Request | Neighbor Solicitation (NS) | 135 |
|
||
| ARP Reply | Neighbor Advertisement (NA) | 136 |
|
||
| gratuitous ARP | Unsolicited NA | 136 |
|
||
| 路由发现 | Router Solicitation / Advertisement | 133 / 134 |
|
||
|
||
> [!tip] 为什么 NDP 更安全?
|
||
> NDP 支持 SEND(Secure Neighbor Discovery,RFC 3971),利用加密签名防止伪装。虽然部署不多,但架构上比明文 ARP 好得多。
|
||
|
||
## 关联笔记
|
||
|
||
- [[hhs/NETWORK/MAC地址与广播域]] — ARP 如何在广播域中工作
|
||
- [[hhs/NETWORK/Switch与路由器]] — Switch 如何处理 ARP 包
|
||
- [[hhs/NETWORK/OSI与TCP-IP模型对比]] — ARP 跨越链路层和网络层的边界
|