实战指南:用Python和Scapy模拟ARP请求与响应(附完整代码)

在网络安全领域,ARP协议作为局域网通信的基础协议,其重要性不言而喻。但对于初学者而言,理解ARP协议的工作原理往往停留在理论层面,缺乏直观的实践体验。本文将带你用Python的Scapy库,从零开始构建ARP请求与响应的完整实验环境,通过代码实操深入理解ARP协议的本质。

1. 环境准备与Scapy基础

1.1 为什么选择Scapy?

Scapy是一个强大的Python网络数据包操作库,相比传统的C语言实现,它具有几个显著优势:

  • 交互式调试:支持实时数据包构建和解析
  • 跨平台:Windows/Linux/macOS全平台兼容
  • 协议覆盖广:支持从二层到七层的协议栈操作
  • 代码简洁:相比C语言的套接字编程,代码量减少80%

安装Scapy非常简单,只需执行:

pip install scapy

1.2 实验网络拓扑

我们需要准备以下实验环境:

设备角色IP地址MAC地址(示例)
攻击者主机192.168.1.1000:0c:29:12:34:56
目标主机192.168.1.2000:0c:29:ab:cd:ef
网关192.168.1.100:50:56:c0:00:08

提示:在实际实验中,请使用ifconfig(Linux/macOS)或ipconfig(Windows)查看本机真实网络配置

2. ARP请求实战

2.1 构建ARP请求包

Scapy中构建ARP请求只需要几行代码:

from scapy.all import *

def send_arp_request(target_ip):
    # 构造ARP请求包
    arp_request = ARP(pdst=target_ip)
    # 构造以太网帧
    ether_frame = Ether(dst="ff:ff:ff:ff:ff:ff")  # 广播地址
    # 组合数据包
    packet = ether_frame/arp_request
    # 发送并接收响应
    answered = srp(packet, timeout=2, verbose=False)[0]
    
    return answered[0][1].hwsrc if answered else None

关键参数解析:

  • pdst: 目标IP地址(要查询的设备)
  • hwdst: 目标MAC地址(请求时设为全F广播地址)
  • op: 操作类型(1为请求,2为响应)

2.2 解析ARP响应

当收到ARP响应时,我们可以这样解析:

mac = send_arp_request("192.168.1.20")
if mac:
    print(f"目标设备MAC地址: {mac}")
else:
    print("未收到ARP响应")

典型问题排查:

  1. 无响应情况

    • 检查目标IP是否在线
    • 确认网络防火墙未阻止ARP包
    • 使用Wireshark抓包验证请求是否发出
  2. 错误响应

    • 验证网络是否存在ARP欺骗
    • 检查本地ARP缓存是否被污染

3. ARP响应模拟

3.1 构建ARP响应服务器

我们可以用Scapy模拟一个ARP响应服务:

from scapy.all import *

def arp_responder():
    def handle_packet(pkt):
        if ARP in pkt and pkt[ARP].op == 1:  # 判断是否为ARP请求
            reply = ARP(
                pdst=pkt[ARP].psrc,
                hwdst=pkt[ARP].hwsrc,
                psrc=pkt[ARP].pdst,
                hwsrc="00:11:22:33:44:55",  # 伪造的MAC地址
                op=2
            )
            send(reply, verbose=False)
    
    sniff(prn=handle_packet, filter="arp", store=0)

arp_responder()

3.2 高级应用:ARP监控

结合Scapy的嗅探功能,可以构建ARP监控系统:

from scapy.all import *
import time

arp_table = {}

def monitor_arp(pkt):
    if ARP in pkt:
        ip = pkt[ARP].psrc
        mac = pkt[ARP].hwsrc
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
        
        if ip in arp_table:
            if arp_table[ip]['mac'] != mac:
                print(f"[!] ARP欺骗警报 {timestamp}: {ip} 的MAC从 {arp_table[ip]['mac']} 变为 {mac}")
        else:
            print(f"[+] 新设备发现: {ip} -> {mac}")
        
        arp_table[ip] = {'mac': mac, 'time': timestamp}

sniff(prn=monitor_arp, filter="arp", store=0)

4. 安全防护与实战技巧

4.1 ARP防御策略

针对ARP欺骗的防护措施:

  1. 静态ARP绑定

    # Linux静态ARP绑定示例
    sudo arp -s 192.168.1.1 00:50:56:c0:00:08
    
  2. 网络设备防护

    • 启用交换机的端口安全功能
    • 配置DHCP Snooping+ARP Inspection
  3. 软件解决方案

    • 使用ARP防火墙工具
    • 定期清理ARP缓存

4.2 实战调试技巧

当你的ARP程序不工作时,可以按照以下步骤排查:

  1. 基础检查

    # 检查网卡是否支持混杂模式
    print(conf.ifaces)
    # 设置正确的网卡接口
    conf.iface = "eth0"
    
  2. 数据包验证

    # 查看构造的数据包
    packet.show()
    # 十六进制转储
    hexdump(packet)
    
  3. 权限问题

    • Linux/Mac需要root权限运行
    • Windows可能需要管理员权限

5. 进阶应用:ARP扫描工具开发

结合前面知识,我们可以开发一个简易的ARP扫描器:

from scapy.all import *
import ipaddress

def arp_scan(network):
    online_hosts = {}
    network = ipaddress.ip_network(network)
    
    # 构造ARP请求包
    arp_request = ARP(pdst=str(network))
    ether_frame = Ether(dst="ff:ff:ff:ff:ff:ff")
    packet = ether_frame/arp_request
    
    # 发送并接收响应
    answered, _ = srp(packet, timeout=2, verbose=False)
    
    for sent, received in answered:
        online_hosts[received.psrc] = received.hwsrc
    
    return online_hosts

results = arp_scan("192.168.1.0/24")
for ip, mac in results.items():
    print(f"{ip:15} -> {mac}")

优化方向:

  1. 多线程扫描:加快大网段扫描速度
  2. 结果可视化:生成网络拓扑图
  3. 持久化存储:将结果保存到数据库

6. 真实案例:解决ARP缓存污染

在一次实际网络故障排查中,我们发现某些设备间歇性无法上网。通过以下Scapy脚本发现了问题根源:

from scapy.all import *
import time

gateway_ip = "192.168.1.1"
gateway_mac = "00:50:56:c0:00:08"
check_interval = 60  # 秒

def check_arp():
    while True:
        current_mac = sr1(ARP(pdst=gateway_ip), timeout=2, verbose=False)
        if current_mac and current_mac.hwsrc != gateway_mac:
            print(f"[警报] 网关MAC地址异常: {current_mac.hwsrc}")
            # 自动修复ARP缓存
            send(ARP(op=2, pdst=gateway_ip, hwdst="ff:ff:ff:ff:ff:ff", 
                    psrc=gateway_ip, hwsrc=gateway_mac), verbose=False)
        time.sleep(check_interval)

check_arp()

这个案例教会我们:网络监控不能只依赖静态配置,动态检测才是王道。通过定期验证关键网络设备的ARP信息,可以及时发现并修复ARP欺骗攻击。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐