| name | detecting-arp-poisoning-in-network-traffic |
| description | 使用 ARPWatch、动态 ARP 检测(Dynamic ARP Inspection)、Wireshark 分析和自定义监控脚本检测和防止 ARP 欺骗(ARP spoofing)攻击,防御中间人(man-in-the-middle)拦截。 |
| domain | cybersecurity |
| subdomain | network-security |
| tags | ["arp-poisoning","arp-spoofing","mitm","dynamic-arp-inspection","arpwatch","network-security","man-in-the-middle","layer-2-security"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
检测网络流量中的 ARP 投毒
概述
ARP 投毒(ARP poisoning,又称 ARP 欺骗)是一种二层(Layer 2)攻击,攻击者发送伪造的 ARP 消息,将其 MAC 地址与合法主机的 IP 地址关联,从而实现中间人(MITM)拦截、会话劫持或拒绝服务攻击。由于 ARP 没有内置身份验证机制,广播域上的任何设备都可以伪造 ARP 应答。检测需要监控 ARP 流量中的异常,如免费 ARP(gratuitous ARP)洪水、IP 到 MAC 映射变化和重复 IP 地址。本技能涵盖部署多层检测,包括 ARPWatch、动态 ARP 检测(DAI)、基于 Wireshark 的分析和自定义 Python 监控工具。
前置条件
- 访问目标网络分段(广播域)
- 用于 ARPWatch 和自定义监控工具的 Linux 主机
- 支持动态 ARP 检测的托管交换机(Cisco Catalyst、Aruba、Juniper EX)
- 用于数据包捕获的 Wireshark 或 tcpdump
- 已配置 DHCP 嗅探(DAI 的前置条件)
- 网络监控基础设施(SIEM、syslog 服务器)
核心概念
ARP 协议基础
ARP 在本地网段将 IP 地址映射到 MAC 地址。该协议以无状态方式运行,没有身份验证:
正常 ARP 过程:
1. 主机 A 广播:"谁有 10.0.1.1?请告诉 10.0.1.100"
2. 路由器回复:"10.0.1.1 在 AA:BB:CC:DD:EE:01"
3. 主机 A 缓存该映射
ARP 投毒攻击:
1. 攻击者向主机 A 发送未请求的 ARP 应答:
"10.0.1.1 在 EV:IL:MA:CA:DD:RR"(攻击者的 MAC)
2. 主机 A 更新缓存,将流量发送给攻击者
3. 攻击者转发给真实网关(中间人位置)
攻击指标
| 指标 | 描述 | 严重性 |
|---|
| MAC 地址反复跳变 | 同一 IP 快速映射到不同 MAC | 高 |
| 免费 ARP 洪水 | 针对多台主机的未请求 ARP 应答 | 高 |
| 重复 IP 地址 | 两个不同 MAC 声称相同 IP | 严重 |
| 异常 ARP 数量 | ARP 每秒数据包数峰值 | 中 |
| 来自非 DHCP 源的 ARP | 来自未知设备的静态 IP 声明 | 中 |
| 网关 MAC 变更 | 默认网关 MAC 地址更改 | 严重 |
实施步骤
步骤 1:部署 ARPWatch 进行持续监控
sudo apt-get install -y arpwatch
sudo vi /etc/default/arpwatch
sudo systemctl enable arpwatch
sudo systemctl start arpwatch
cat /var/lib/arpwatch/arp.dat
tail -f /var/log/syslog | grep arpwatch
ARPWatch 告警类型:
- new station - 之前未见过的 MAC 地址
- changed ethernet address - IP 映射到不同 MAC(可能是投毒)
- flip flop - MAC 在两个地址间交替(主动攻击)
- reused old ethernet address - 之前见过的映射重新出现
步骤 2:在交换机上配置动态 ARP 检测(DAI)
Cisco Catalyst 配置:
! 启用 DHCP 嗅探(DAI 的前置条件)
ip dhcp snooping
ip dhcp snooping vlan 10,20,30
! 配置可信端口(上行链路、DHCP 服务器)
interface GigabitEthernet1/0/1
description Uplink to Distribution
ip dhcp snooping trust
interface GigabitEthernet1/0/48
description DHCP Server
ip dhcp snooping trust
! 启用动态 ARP 检测
ip arp inspection vlan 10,20,30
! 配置 DAI 的可信端口
interface GigabitEthernet1/0/1
ip arp inspection trust
! 设置速率限制以防止 ARP 洪水 DoS
interface range GigabitEthernet1/0/2-47
ip arp inspection limit rate 15
! 启用额外的验证检查
ip arp inspection validate src-mac dst-mac ip
! 为静态 IP 设备配置 ARP ACL(服务器、打印机)
arp access-list STATIC-ARP-ENTRIES
permit ip host 10.0.10.100 mac host 0011.2233.4455
permit ip host 10.0.10.101 mac host 0011.2233.4456
ip arp inspection filter STATIC-ARP-ENTRIES vlan 10
! 验证 DAI 状态
show ip arp inspection vlan 10
show ip arp inspection statistics
show ip dhcp snooping binding
步骤 3:Wireshark 检测过滤器
# 检测免费 ARP(发送方和目标 IP 相同)
arp.src.proto_ipv4 == arp.dst.proto_ipv4
# 检测 ARP 应答(关注未请求的)
arp.opcode == 2
# 检测重复 IP 地址声明
arp.duplicate-address-detected
# 检测来自特定攻击者 MAC 的 ARP 数据包
eth.src == ev:il:ma:ca:dd:rr
# 检测 ARP 风暴(高流量)
# 使用 Statistics > I/O Graphs > 显示过滤器:arp
# 检测网关冒充
arp.src.proto_ipv4 == 10.0.1.1 && arp.src.hw_mac != aa:bb:cc:dd:ee:01
步骤 4:自定义 Python ARP 监控器
"""
使用数据包捕获进行实时 ARP 投毒检测。
监控 ARP 流量中的欺骗指标并在异常时发出告警。
"""
import subprocess
import sys
import json
import time
from collections import defaultdict
from datetime import datetime
try:
from scapy.all import sniff, ARP, Ether, get_if_hwaddr, conf
SCAPY_AVAILABLE = True
except ImportError:
SCAPY_AVAILABLE = False
class ARPPoisonDetector:
def __init__(self, interface: str, gateway_ip: str, gateway_mac: str):
self.interface = interface
self.gateway_ip = gateway_ip
self.gateway_mac = gateway_mac.lower()
self.arp_table = {}
self.arp_history = defaultdict(list)
self.alerts = []
self.arp_count = defaultdict(int)
self.last_reset = time.time()
self.arp_rate_threshold = 50
def alert(self, severity: str, message: , details: ):
alert_data = {
: datetime.now().isoformat(),
: severity,
: message,
: details,
}
.alerts.append(alert_data)
()
key, value details.items():
()
():
src_ip == .gateway_ip src_mac != .gateway_mac:
.alert(, , {
: .gateway_ip,
: .gateway_mac,
: src_mac,
: ,
})
():
src_ip .arp_table:
known_mac = .arp_table[src_ip]
known_mac != src_mac:
.alert(, , {
: src_ip,
: known_mac,
: src_mac,
: ,
})
():
.arp_history[src_ip].append((src_mac, time.time()))
cutoff = time.time() -
.arp_history[src_ip] = [
(mac, ts) mac, ts .arp_history[src_ip]
ts > cutoff
]
unique_macs = (mac mac, ts .arp_history[src_ip])
(unique_macs) > :
.alert(, , {
: src_ip,
: (unique_macs),
: (.arp_history[src_ip]),
})
():
.arp_count[src_mac] +=
time.time() - .last_reset > :
mac, count .arp_count.items():
count > .arp_rate_threshold:
.alert(, , {
: mac,
: count,
: .arp_rate_threshold,
})
.arp_count.clear()
.last_reset = time.time()
():
packet.haslayer(ARP):
arp = packet[ARP]
arp.op (, ):
src_ip = arp.psrc
src_mac = arp.hwsrc.lower()
.check_gateway_spoofing(src_ip, src_mac)
.check_mac_change(src_ip, src_mac)
.check_flip_flop(src_ip, src_mac)
.check_arp_rate(src_mac)
.arp_table[src_ip] = src_mac
():
()
()
()
SCAPY_AVAILABLE:
sniff(
iface=.interface,
=,
prn=.process_packet,
store=,
)
:
()
()
._monitor_with_tcpdump()
():
cmd = [, , .interface, , , ]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, text=)
:
line proc.stdout:
parts = line.strip().split()
parts:
:
ip_idx = parts.index() -
mac_idx = parts.index() +
src_ip = parts[ip_idx]
src_mac = parts[mac_idx].lower()
.check_gateway_spoofing(src_ip, src_mac)
.check_mac_change(src_ip, src_mac)
.arp_table[src_ip] = src_mac
(IndexError, ValueError):
KeyboardInterrupt:
proc.terminate()
() -> :
{
: .interface,
: {: .gateway_ip, : .gateway_mac},
: (.alerts),
: (.arp_table),
: .alerts,
}
__name__ == :
(sys.argv) < :
()
()
sys.exit()
detector = ARPPoisonDetector(
interface=sys.argv[],
gateway_ip=sys.argv[],
gateway_mac=sys.argv[],
)
:
detector.start_monitoring()
KeyboardInterrupt:
()
report = detector.generate_report()
()
()
预防措施
二层控制
- 动态 ARP 检测(DAI) - 根据 DHCP 嗅探绑定表验证 ARP 数据包
- DHCP 嗅探 - 构建可信的 IP-MAC-端口绑定数据库
- 端口安全 - 限制每个端口的 MAC 地址数
- 私有 VLAN - 限制同一 VLAN 中主机之间的通信
网络控制
- 静态 ARP 条目 - 用于关键基础设施(网关、DNS、DHCP)
- 网络分段 - 使用 VLAN 减小广播域大小
- 802.1X 认证 - 在网络访问前对设备进行身份验证
- 加密协议 - 使用 SSH、HTTPS、TLS 保护数据,即使被拦截也是安全的
最佳实践
- 纵深防御 - 结合 DAI、ARPWatch 和自定义监控实现全面覆盖
- 先配置 DHCP 嗅探 - 在 DAI 之前始终启用 DHCP 嗅探(DAI 依赖嗅探数据库)
- 为网关配置静态 ARP - 在关键服务器上为默认网关配置静态 ARP 条目
- 监控免费 ARP - 特别关注未请求的 ARP 应答
- 小广播域 - 使用 VLAN 限制 ARP 攻击的范围
- 定期审计 - 定期比较各设备上的 ARP 表以识别异常
参考资料
- NIST SP 800-54 - 边界网关协议安全
- Cisco DAI 配置指南
- MITRE ATT&CK T1557.002 — ARP 缓存投毒