我需要读取PCAP文件,修改一些字段(实际上是IPv4源和目标以及以太网源和目标)。 PCAP经过预过滤,仅包含IPv4 over Ethernet数据包。
到目前为止,我尝试用scapy做这个,但是有严重的内存问题。读取~350MB的PCAP文件时,我的16GB RAM完全填满。实际上,只是阅读。我还没有对此文件做任何其他事情。我也有found this answer,随着这些变化,阅读速度非常快。一旦我开始修改数据包,内存就会再次膨胀。事实上,Scapy在这种情况下无法使用
我还考虑过使用其他工具,比如tcprewrite,但它无法满足我的需求。每个数据包的源MAC始终相同,这也可以使用tcprewrite完成。源IP在给定的子网范围内应该是随机的,例如在10.0.0.0/16中均匀分布。不太容易。更复杂的是目标IP,需要从给定的流量矩阵中计算出来。
所以问题是:如何读取PCAP文件,使用自定义函数修改四个基本字段(Ethernet src + dst,IP src + dst),并将其写回(另一个)PCAP文件?
实际上,我的框架的其余部分是用Python编写的,所以我更喜欢基于python的解决方案。但是,因为我可以简单地调用其他脚本,这不是强制性的。谢谢!
答案 0 :(得分:1)
Scapy似乎有一个严重的内存问题",正如你所说,可能是因为你用rdpcap()
读取内存中的整个PCAP文件然后修改它(仍在内存中),然后写它使用wrpcap()
从您的记忆中一次性回到另一个文件。
但最多" Pythonic"和#34; Scapyist"做这种事情的方法是使用生成器(PcapReader
和PcapWriter
)。这是一个例子:
from scapy.all import *
ETHER_ADDR_TRANSLATION = {
"orig_mac_1": "new_mac_1",
# [...]
}
IP_ADDR_TRANSLATION = {
"orig_ip_1": "new_ip_1",
# [...]
}
def addr_translation_pcap(source, destination):
out = PcapWriter(destination)
for pkt in PcapReader(source):
# In case we have complex encapsulations, like IP-in-IP, etc.,
# we have to do something like this. If we know for sure that's
# not the case, there's no need for such a (time-consuming) code.
layer = pkt
while not isinstance(layer, NoPayload):
if isinstance(layer, Ether):
for field in ['src', 'dst']:
fval = getattr(layer, field)
if fval in ETHER_ADDR_TRANSLATION:
setattr(layer, field, ETHER_ADDR_TRANSLATION[fval])
# Let's not forget IP-in-ICMP-error
elif isinstance(layer, (IP, IPerror)):
for field in ['src', 'dst']:
fval = getattr(layer, field)
if fval in IP_ADDR_TRANSLATION:
setattr(layer, field, IP_ADDR_TRANSLATION[fval])
elif isinstance(layer, ARP):
fields = {}
if layer.hwtype == 1:
fields.update({'hwsrc': ETHER_ADDR_TRANSLATION,
'hwdst': ETHER_ADDR_TRANSLATION})
if layer.ptype == 2048:
fields.update({'psrc': IP_ADDR_TRANSLATION,
'pdst': IP_ADDR_TRANSLATION})
for field, translator in fields.iteritems():
fval = getattr(layer, field)
if fval in translator:
setattr(layer, field, translator[fval])
layer = layer.payload
out.write(pkt)
out.close()
答案 1 :(得分:0)
我不知道是否有办法用scapy做到这一点,但您也可以使用非常简单的PcapFile.py库,它允许您逐包读/写pcap文件(免责声明:I& #39; m其中一位作者)。如果您的需求不是太复杂(例如,您不需要重新生成校验和),您可以使用Python切片和Python的struct模块简单地修改框架的字节串。
但我认为也应该可以使用p = Ether(packet_bytes)
分析帧并使用str(p)
转换回PcapFile.py的字节流。这样你就可以让scapy为你重新计算一个有效的校验和。