Skip to main content
 首页 » 编程设计

python之Scapy 中的错误行为

2025年05月04日11Leo_wl

我使用 Scapy 的函数 send 发送数据包,这些数据包将在路由器上生成 ICMP 数据包,并使用作为子进程启动的 tcpdump 转储这些 ICMP 数据包。

然后,我将使用 scapy 的内置 rdpcap 函数将这些 ICMP 数据包读回我的程序。

好吧,事实证明 rdpcap 有时会弄乱一些东西,只要我想查看捕获的数据包,它就会返回以下内容:

(InteractiveConsole) 
>>> icmpPackets 
Traceback (most recent call last): 
  File "<console>", line 1, in <module> 
  File "/usr/lib/python2.7/dist-packages/scapy/plist.py", line 57, in __repr__ 
    if self._elt2pkt(r).haslayer(p): 
AttributeError: 'NoneType' object has no attribute 'haslayer' 

然后,我只需要在 same 参数上再次调用 rdpcap,一切都会恢复正常:

>>> icmpPackets = rdpcap(tcpdumpFileName) 
>>> icmpPackets 
<icmpPackets.cap: TCP:0 UDP:0 ICMP:1428 Other:1> 

这是一些错误,对吧?

编辑:好的,在出现该错误之前我做的一件事如下,这可能不是太正统,但我在伪造数据包时不需要以太网层。如果我删除这两行,我将不会收到任何此类错误:

for i in range(len(icmpPackets)): 
        icmpPackets[i] = icmpPackets[i].getlayer(IP) 

我之前在其他地方做过这个,从来没有遇到过问题。这里发生了什么?

请您参考如下方法:

嗨,

我真的不明白为什么你用 tcpdump 而不是 scapy 来嗅探流量,但无论如何......你的问题不是 Scapy 中的错误而是你的代码中的错误。您正在用它的 .getlayer(IP) 替换每个数据包,如果数据包没有 IP 层(例如 ARP 数据包)。因此,你得到了后者的异常(exception)。

我认为你应该更换

icmpPackets = rdpcap(tcpdumpFileName) 
for i in range(len(icmpPackets)): 
    icmpPackets[i] = icmpPackets[i].getlayer(IP) 

与

icmpPackets = PacketList([p[IP] for p in PcapReader(tcpdumpFileName) if IP in p]) 

首先,我认为它更“Pythonic”,而且它通过删除没有IP 层的数据包来解决问题。或者你也可以使用,如果你想要没有 Ether 层的所有数据包:

icmpPackets = PacketList([p.payload for p in PcapReader(tcpdumpFileName)]) 

此外,您可以在 tcpdump 中使用 BPF 过滤器进行过滤(icmp 如果您只想要 ICMP 数据包)。