Scapy在Windows下发送数据包后嗅探到自身发送包的问题排查
Scapy在Windows下Sniff到自身发送数据包的原因与解决办法
这个问题的核心根源在于Windows和Linux的网络捕获驱动默认行为差异,具体细节如下:
根本原因
- 在Linux系统中,Scapy使用的原生
PF_PACKET二层套接字默认不会捕获本地发送的数据包——内核会自动把自身发出的包从嗅探队列中排除,所以你只能抓到来自其他设备的响应。 - 而在Windows上,Scapy依赖WinPcap或Npcap驱动来实现二层数据包的捕获与发送。这两个驱动的默认配置是捕获所有经过网卡的数据包,包括从网卡发送出去的流量(驱动会把发送的包回环给嗅探进程),所以你调用
s.sniff()时会拿到自己刚发送的数据包。
可行的解决办法
1. 在Sniff时过滤本地MAC地址
最简单直接的方式是在嗅探时添加过滤规则,排除源MAC为本地网卡的数据包:
from scapy.all import get_if_hwaddr def sendOneFast(pkt): """ Function: sendOneFast Purpose: Opens a layer 2 socket on interface, sends a packet on that socket. pkt -> Scapy packet to be sent """ iface = 'Intel(R) Ethernet Connection (2) I219-LM #2' local_mac = get_if_hwaddr(iface) s = conf.L2socket(iface=iface) s.send(pkt) # 过滤掉源MAC是本地网卡的包 l = s.sniff(iface=iface, timeout=0.03, filter=f"ether src != {local_mac}") return l
这个方法利用BPF过滤规则直接在驱动层面过滤掉不需要的包,效率很高。
2. 调整WinPcap/Npcap的捕获配置
如果你不想修改代码,可以尝试调整驱动的设置:
- 对于Npcap,在安装时可以选择关闭“捕获自己发送的数据包”选项;如果已经安装,也可以在Npcap的配置工具里修改这个参数。
- 注意:这种全局设置会影响所有使用该驱动的程序,灵活性不如代码层面的过滤。
3. 分离发送与嗅探线程(进阶方案)
如果担心同步问题,可以用线程分开发送和嗅探操作,再过滤结果:
from scapy.all import conf, get_if_hwaddr, Ether from threading import Thread def send_packet(pkt, iface): s = conf.L2socket(iface=iface) s.send(pkt) def sniff_response(iface, timeout, result_list): s = conf.L2socket(iface=iface) result_list.extend(s.sniff(iface=iface, timeout=timeout)) def sendOneFast(pkt): iface = 'Intel(R) Ethernet Connection (2) I219-LM #2' result = [] # 启动嗅探线程 sniff_thread = Thread(target=sniff_response, args=(iface, 0.03, result)) sniff_thread.start() # 启动发送线程 send_thread = Thread(target=send_packet, args=(pkt, iface)) send_thread.start() # 等待嗅探结束 sniff_thread.join() # 过滤本地发出的包 local_mac = get_if_hwaddr(iface) filtered_result = [p for p in result if p[Ether].src != local_mac] return filtered_result
这种方式可以避免因发送和嗅探的时序问题导致漏抓响应,同时保证只返回目标数据包。
内容的提问来源于stack exchange,提问作者Austin A
相关产品推荐
相关产品推荐

