Scapy发送带Ethernet层数据包失败,仅IP层数据包正常问题咨询
问题分析:为什么带Ethernet层的Scapy数据包无法被目标主机接收?
首先得明确Scapy里send()和sendp()的核心差异,这也是你遇到问题的关键:
send()是网络层发送函数:它会自动帮你搞定链路层的所有封装工作——包括根据目标IP执行ARP解析拿到对应MAC地址、选择正确的发送网卡、填充Ethernet帧的源/目的MAC字段,最后才发送数据包。sendp()是链路层发送函数:它完全依赖你手动构建的Ethernet帧头,不会自动做ARP解析或网卡路由选择,如果你只写Ether()却不指定关键参数,自然会出问题。
你的问题根源就在这里:当你用Ether() / IP(dst='192.168.0.6') / TCP(dport=8000)构建数据包时,Ether()默认用的是广播MAC地址(ff:ff:ff:ff:ff:ff)。如果你的主机有多块网卡,sendp()还可能选错发送网卡,导致数据包根本没进入目标主机所在的局域网;就算数据包广播出去了,部分主机的网卡或协议栈可能会过滤广播帧,或者你的Wireshark过滤规则没包含广播帧,看起来就像没收到一样。
解决方法
要让带Ethernet层的数据包正常被目标接收,你可以试试下面几种方式:
方法1:手动指定目标MAC地址
先通过终端命令arp -a查询目标IP对应的MAC,然后在Ether层中明确指定:
packet = Ether(dst="aa:bb:cc:dd:ee:ff") / IP(dst='192.168.0.6') / TCP(dport=8000) sendp(packet)
方法2:让Scapy自动解析ARP获取MAC
用Scapy自带的getmacbyip()函数自动获取目标IP的MAC,更灵活省心:
from scapy.all import getmacbyip target_mac = getmacbyip('192.168.0.6') packet = Ether(dst=target_mac) / IP(dst='192.168.0.6') / TCP(dport=8000) sendp(packet)
方法3:指定发送网卡(多网卡主机必看)
如果你的主机有多个网卡,一定要在sendp()里加iface参数,确保数据包从正确的网卡发出:
target_mac = getmacbyip('192.168.0.6') packet = Ether(dst=target_mac) / IP(dst='192.168.0.6') / TCP(dport=8000) sendp(packet, iface="eth0") # 替换成你的目标网卡名称,比如Windows上的"以太网"
额外验证建议
在目标主机的Wireshark里,你可以设置过滤规则ether dst aa:bb:cc:dd:ee:ff or ether dst ff:ff:ff:ff:ff:ff(替换成目标MAC或广播MAC),这样就能看到广播帧或者指定MAC的帧,确认数据包是否真的到达了目标主机。
内容的提问来源于stack exchange,提问作者BeldCode




