知识点编号:032
难度等级:⭐⭐⭐(掌握)
面试频率:🔥🔥🔥🔥🔥
🎯 一句话总结
ARP就像通讯录,把IP地址(名字)翻译成MAC地址(电话号码)!📞
🤔 ARP是什么?
ARP:Address Resolution Protocol
地址解析协议
作用:
把IP地址(网络层)映射到MAC地址(链路层)
为什么需要ARP?
- IP地址:逻辑地址,可变(如192.168.1.10)
- MAC地址:物理地址,固定(如AA:BB:CC:DD:EE:FF)
- 数据链路层需要MAC地址来传输数据
生活比喻:
你知道朋友的名字(IP地址)
但要打电话,需要查通讯录找到电话号码(MAC地址)
ARP就是这个通讯录!📱
🎮 ARP工作过程
场景:主机A(192.168.1.10)要发数据给主机B(192.168.1.20)
完整流程:
主机A 主机B
IP: 192.168.1.10 IP: 192.168.1.20
MAC: AA:BB:CC:DD:EE:FF MAC: 11:22:33:44:55:66
步骤1:检查ARP缓存
主机A查看本地ARP表
192.168.1.20 → ?(没有记录)
步骤2:发送ARP请求(广播)
┌─────────────────────────────────┐
│ 以太网帧头 │
│ 目标MAC:FF:FF:FF:FF:FF:FF(广播)│
│ 源MAC:AA:BB:CC:DD:EE:FF │
├─────────────────────────────────┤
│ ARP请求 │
│ 类型:Request(1) │
│ 发送方IP:192.168.1.10 │
│ 发送方MAC:AA:BB:CC:DD:EE:FF │
│ 目标IP:192.168.1.20(要查询的) │
│ 目标MAC:00:00:00:00:00:00(未知)│
└─────────────────────────────────┘
主机A ─────广播─────> 所有主机
步骤3:主机B收到ARP请求
- 检查目标IP是否是自己
- 是!192.168.1.20是我
- 记录主机A的IP和MAC
- 准备回复
步骤4:发送ARP应答(单播)
┌─────────────────────────────────┐
│ 以太网帧头 │
│ 目标MAC:AA:BB:CC:DD:EE:FF(A) │
│ 源MAC:11:22:33:44:55:66(B) │
├─────────────────────────────────┤
│ ARP应答 │
│ 类型:Reply(2) │
│ 发送方IP:192.168.1.20 │
│ 发送方MAC:11:22:33:44:55:66 │
│ 目标IP:192.168.1.10 │
│ 目标MAC:AA:BB:CC:DD:EE:FF │
└─────────────────────────────────┘
主机B ─────单播─────> 主机A
步骤5:主机A更新ARP缓存
192.168.1.20 → 11:22:33:44:55:66
步骤6:正常通信
现在可以发送数据了!
目标MAC:11:22:33:44:55:66
📋 ARP报文格式
ARP报文结构:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 硬件类型(16) | 协议类型(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 硬件地址长度(8) | 协议地址长度(8)| 操作码(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 发送方MAC地址(前4字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 发送方MAC地址(后2字节) | 发送方IP地址(前2字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 发送方IP地址(后2字节) | 目标MAC地址(前2字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目标MAC地址(后4字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目标IP地址(4字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段说明:
硬件类型:
1 = 以太网
协议类型:
0x0800 = IPv4
硬件地址长度:
6(MAC地址6字节)
协议地址长度:
4(IPv4地址4字节)
操作码:
1 = ARP请求
2 = ARP应答
3 = RARP请求
4 = RARP应答
💻 查看和管理ARP缓存
Linux/Mac
# 查看ARP缓存表
arp -a
arp -n # 不解析域名,只显示IP
输出示例:
? (192.168.1.1) at aa:bb:cc:dd:ee:ff [ether] on eth0
? (192.168.1.20) at 11:22:33:44:55:66 [ether] on eth0
# 添加静态ARP条目
sudo arp -s 192.168.1.100 aa:bb:cc:dd:ee:ff
# 删除ARP条目
sudo arp -d 192.168.1.100
# 清空ARP缓存
sudo ip -s -s neigh flush all
Windows
# 查看ARP缓存表
arp -a
输出示例:
接口: 192.168.1.10 --- 0x2
Internet 地址 物理地址 类型
192.168.1.1 aa-bb-cc-dd-ee-ff 动态
192.168.1.20 11-22-33-44-55-66 动态
# 添加静态ARP条目
arp -s 192.168.1.100 aa-bb-cc-dd-ee-ff
# 删除ARP条目
arp -d 192.168.1.100
# 清空ARP缓存
netsh interface ip delete arpcache
💻 Java代码示例
import java.net.*;
import java.io.*;
import java.util.*;
public class ARPTool {
/**
* 获取ARP缓存表
*/
public static void showARPTable() {
try {
String os = System.getProperty("os.name").toLowerCase();
String command = os.contains("win") ? "arp -a" : "arp -n";
System.out.println("=== ARP缓存表 ===\n");
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
process.waitFor();
} catch (Exception e) {
System.err.println("获取ARP表失败: " + e.getMessage());
}
}
/**
* 解析ARP表
*/
public static Map<String, String> parseARPTable() {
Map<String, String> arpTable = new HashMap<>();
try {
String os = System.getProperty("os.name").toLowerCase();
String command = os.contains("win") ? "arp -a" : "arp -n";
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
String line;
while ((line = reader.readLine()) != null) {
// 解析Windows格式
if (os.contains("win")) {
// 192.168.1.1 aa-bb-cc-dd-ee-ff 动态
String[] parts = line.trim().split("\\s+");
if (parts.length >= 2 &&
parts[0].matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) {
arpTable.put(parts[0], parts[1].replace("-", ":"));
}
}
// 解析Linux格式
else {
// 192.168.1.1 ether aa:bb:cc:dd:ee:ff C eth0
String[] parts = line.split("\\s+");
if (parts.length >= 3 &&
parts[0].matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) {
arpTable.put(parts[0], parts[2]);
}
}
}
reader.close();
process.waitFor();
} catch (Exception e) {
System.err.println("解析ARP表失败: " + e.getMessage());
}
return arpTable;
}
/**
* 查询指定IP的MAC地址
*/
public static String getMACAddress(String ip) {
Map<String, String> arpTable = parseARPTable();
return arpTable.getOrDefault(ip, "未找到");
}
/**
* 获取本机MAC地址
*/
public static String getLocalMAC() {
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
return "未找到";
}
byte[] mac = network.getHardwareAddress();
if (mac == null) {
return "未找到";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s",
mac[i], (i < mac.length - 1) ? ":" : ""));
}
return sb.toString();
} catch (Exception e) {
return "错误: " + e.getMessage();
}
}
/**
* 获取网关MAC地址
*/
public static String getGatewayMAC() {
try {
// 获取默认网关IP
String gatewayIP = getDefaultGateway();
if (gatewayIP == null) {
return "未找到网关";
}
// 查询网关的MAC地址
return getMACAddress(gatewayIP);
} catch (Exception e) {
return "错误: " + e.getMessage();
}
}
/**
* 获取默认网关IP
*/
private static String getDefaultGateway() {
try {
String os = System.getProperty("os.name").toLowerCase();
String command;
if (os.contains("win")) {
command = "ipconfig";
} else {
command = "ip route";
}
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
String line;
while ((line = reader.readLine()) != null) {
if (os.contains("win")) {
if (line.contains("默认网关") || line.contains("Default Gateway")) {
String[] parts = line.split(":");
if (parts.length >= 2) {
return parts[1].trim();
}
}
} else {
if (line.contains("default via")) {
String[] parts = line.split("\\s+");
if (parts.length >= 3) {
return parts[2];
}
}
}
}
reader.close();
process.waitFor();
} catch (Exception e) {
System.err.println("获取网关失败: " + e.getMessage());
}
return null;
}
public static void main(String[] args) {
System.out.println("=== ARP工具 ===\n");
// 显示本机MAC
System.out.println("本机MAC地址: " + getLocalMAC());
System.out.println();
// 显示网关MAC
String gatewayIP = getDefaultGateway();
if (gatewayIP != null) {
System.out.println("默认网关IP: " + gatewayIP);
System.out.println("默认网关MAC: " + getGatewayMAC());
System.out.println();
}
// 显示ARP表
showARPTable();
System.out.println();
// 解析并打印ARP表
System.out.println("=== 解析后的ARP表 ===\n");
Map<String, String> arpTable = parseARPTable();
arpTable.forEach((ip, mac) -> {
System.out.println(ip + " -> " + mac);
});
}
}
⚠️ ARP相关问题
1. ARP缓存超时
问题:
ARP缓存有过期时间
Linux:
- 默认60-120秒
- 可配置
Windows:
- 动态条目:2分钟
- 静态条目:永不过期
影响:
- 过期后需要重新ARP请求
- 短暂延迟
解决:
- 对重要主机设置静态ARP
- arp -s 192.168.1.1 aa:bb:cc:dd:ee:ff
2. ARP欺骗攻击
原理:
黑客发送伪造的ARP应答
把网关IP映射到黑客MAC
截获所有流量
过程:
正常:
192.168.1.1 (网关) → aa:bb:cc:dd:ee:ff
攻击后:
192.168.1.1 (网关) → 黑客MAC
所有流量发到黑客
防御:
1. 静态ARP绑定(网关和重要服务器)
2. ARP防火墙
3. 交换机端口安全
4. VLAN隔离
3. 免费ARP(Gratuitous ARP)
定义:
主机主动发送ARP请求
请求自己的IP地址
作用:
1. 检测IP冲突
- 如果收到应答,说明IP被占用
2. 更新其他主机的ARP缓存
- 当MAC地址变化时(如网卡更换)
3. 通知网关
- 主机启动时
示例:
主机A(192.168.1.10)发送:
"谁是192.168.1.10?我是192.168.1.10"
🐛 常见面试题
Q1:ARP协议的工作原理是什么?
答案:
ARP将IP地址映射到MAC地址。
工作过程:
1. 主机A要发数据给主机B
- 知道B的IP(192.168.1.20)
- 不知道B的MAC
2. 检查ARP缓存
- 如果有记录,直接使用
- 如果没有,发送ARP请求
3. ARP请求(广播)
- 目标MAC:FF:FF:FF:FF:FF:FF(广播)
- "谁是192.168.1.20?请告诉192.168.1.10"
4. 主机B收到请求
- 检查目标IP是否是自己
- 是!返回ARP应答
5. ARP应答(单播)
- 目标MAC:主机A的MAC
- "我是192.168.1.20,我的MAC是11:22:33:44:55:66"
6. 主机A更新ARP缓存
- 192.168.1.20 → 11:22:33:44:55:66
- 正常发送数据
特点:
- 请求是广播
- 应答是单播
- 有缓存机制
- 工作在数据链路层
Q2:ARP欺骗是什么?如何防御?
答案:
ARP欺骗:
原理:
黑客发送伪造的ARP应答
欺骗受害者更新ARP缓存
将流量引导到黑客
攻击过程:
1. 黑客发送伪造ARP应答
"网关192.168.1.1的MAC是<黑客MAC>"
2. 受害者更新ARP缓存
192.168.1.1 → <黑客MAC>
3. 受害者的所有流量发到黑客
4. 黑客截获、修改、转发流量
危害:
- 窃听敏感信息
- 篡改数据
- 中间人攻击
- 拒绝服务
防御措施:
1. 静态ARP绑定(推荐)
arp -s 192.168.1.1 aa:bb:cc:dd:ee:ff
2. ARP防火墙
- 监控ARP流量
- 检测异常ARP应答
3. 交换机端口安全
- 绑定端口和MAC
- 限制每个端口的MAC数量
4. VLAN隔离
- 限制ARP广播范围
5. 使用HTTPS/VPN
- 加密流量
- 即使被截获也无法解密
检测:
- 使用arp -a检查网关MAC是否变化
- 使用Wireshark监控ARP流量
- 使用专业工具(如arpwatch)
🎓 总结
ARP协议的关键点:
- 作用:IP地址 → MAC地址
- 过程:请求(广播)→ 应答(单播)
- 缓存:避免重复请求
- 安全:警惕ARP欺骗
记忆口诀:
IP要找MAC地址 🔍
ARP广播发请求 📢
目标主机来应答 ✅
缓存记录供使用 💾
文档创建时间:2025-10-31