使用Scapy更改源/目的地发送pcap数据包

26

我正在尝试使用scapy发送以pcap格式记录的流量。目前,我卡在了去除原始Ether层上。该流量是在另一台主机上捕获的,我基本上需要更改IP和Ether层的源和目标地址。我设法替换IP层并重新计算校验和,但是Ether层让我很困扰。

有没有人有从应用更改后的IP和Ether层(src和dst)重发捕获文件中的数据包的经验?此外,这个捕获文件相当大,几GB左右,使用scapy处理如此大的流量会有什么性能方面的问题吗?


1
"Scapy" 是一个不错的工具,但是你一定要用它来做这件事吗?还有其他可能更适合优化的解决方案... - Mike Pennington
1
麦克,你能推荐一些“其他工具”吗?我觉得Scapy对于这个任务是一个很自然的选择。 - Jason Bart
请查看tcpreplay - Mike Pennington
@MikePennington,tcpreplay能否处理更改源地址和目的地址的请求功能?我查看了一下,但未能找到此功能,这就是我来到此页面的原因。 - Vercingatorix
没关系;您可以使用 tcprewrite 工具的伪NAT选项(例如 -S)和 0.0.0.0/0:<ip>/32(如果您想将所有源地址更改为 <ip>)来首先转换文件,然后使用 tcpreplay 工具进行回放。 - Vercingatorix
4个回答

32

查看此示例

from scapy.all import *
from scapy.utils import rdpcap

pkts=rdpcap("FileName.pcap")  # could be used like this rdpcap("filename",500) fetches first 500 pkts
for pkt in pkts:
     pkt[Ether].src= new_src_mac  # i.e new_src_mac="00:11:22:33:44:55"
     pkt[Ether].dst= new_dst_mac
     pkt[IP].src= new_src_ip # i.e new_src_ip="255.255.255.255"
     pkt[IP].dst= new_dst_ip
     sendp(pkt) #sending packet at layer 2

评论:

  • 使用rdpcap、wrpcap scapy方法从pcap格式文件中读取和写入
  • 您可以使用sniff(offline="filename")来读取数据包,也可以使用prn参数,例如:sniff(offline="filename",prn=My_Function)。在这种情况下,My_Functions将应用于每个被嗅探到的数据包。
  • 正确的编写新的IP或MAC地址的方法是将其视为字符串,例如:ip="1.1.1.1"等,如上所示。
  • 示例中,sendp方法包含在for循环中,这比使用其他循环发送数据包更慢。
  • 性能提示:在Python中,使用for循环太慢了,改用map,如果想要像C语言中的for循环一样快的速度,可以参考此处
  • 上面使用的rdpcap会一次性读取整个文件,如果可用内存仅有1.5GB,而你正在读取2GB、3GB等大小的文件,则会失败。
  • 如果性能问题对你很重要,可以使用winpcap,但需要编写更复杂的C代码;使用Python/Scapy完成相同任务非常容易简单,但速度不如C。
  • 使用哪一个取决于所需的性能级别
  • 如果我猜对了,你正在发送视频流数据包,此时如果我发送的是1兆像素视频,则我会使用winpcap;否则在其他情况下使用scapy(每帧较小)。
  • 如果使用C/winpcap,则可以获得很好的性能来读取pcaps并更改数据并重新发送,但您必须注意相同的问题(大文件),您必须创建具有适当大小的缓冲区以用于读取和发送数据包以实现高性能。
  • 如果数据包大小是恒定的(在大多数情况下很少出现,我猜),您可以利用可用内存的大部分空间。
  • 如果想要在整个“项目/程序”中使用Python/Scapy,则可以在C/winpcap中创建高性能函数并编译为dll,然后将其导入到Python程序中,并在Python程序中使用它。这样,您既可以获得精彩易用的Python/Scapy,又只需在C中编写特定的函数即可更快地完成工作,代码也更加专注和可维护。

2
感谢你的建议,Abdurahman,尤其是关于性能问题的建议!Scapy是一个不错的工具,但可能不适合处理大量流量模拟(至少“开箱即用”情况下)。 - Jason Bart
关于您对使用内置的map的建议,我不确定这是否会提高性能,因为scapy的send/sendp方法接收一个数据包列表作为参数,并且在函数内部它们有一个for循环(__gen_send函数)。因此,也许通过逐个调用map而不是直接将数据包列表传递给send/sendp所获得的优势,在内部的for循环中就会失去。 - newlog
引用原帖:“抓包相当大,有几个GB,使用scapy处理这么多的流量性能如何?”遗憾的是,如果你有一个pcap文件,使用scapy是可能会非常慢的,这是我第一次给出反对票。在低数据包速率下,谁在乎呢?但是在高数据包速率下,scapy就会变得很慢。tcpreplay是高数据包速率下更好的选择。最好的办法是:使用scapy重写一次pcap值,然后使用tcpreplay重复播放。我不知道这是否符合原帖作者的使用情况。 - Mike Pennington

7
如果我是你,我会让Scapy处理层,并使用函数。例如:
ip_map = {"1.2.3.4": "10.0.0.1", "1.2.3.5": "10.0.0.2"}
for p in PcapReader("filename.cap"):
    if IP not in p:
        continue
    p = p[IP]
    # if you want to use a constant map, only let the following line
    p.src = "10.0.0.1"
    p.dst = "10.0.0.2"
    # if you want to use the original src/dst if you don't find it in ip_map
    p.src = ip_map.get(p.src, p.src)
    p.dst = ip_map.get(p.dst, p.dst)
    # if you want to drop the packet if you don't find both src and dst in ip_map
    if p.src not in ip_map or p.dst not in ip_map:
        continue
    p.src = ip_map[p.src]
    p.dst = ip_map[p.dst]
    # as suggested by @AliA, we need to let Scapy compute the correct checksum
    del(p.chksum)
    # then send the packet
    send(p)

3
对我有用,唯一的问题是错误的IP校验和,可以通过在send(p)之前添加del p.chksum来轻松解决。 - AliA

5

使用scapy,我想出了以下方法(对于我的Python表示抱歉)。希望这能帮助到某些人。可能有一种更简单的方案,即将pcap文件中的所有数据包读入内存,但这可能会导致处理大型捕获文件时出现问题。

from scapy.all import *
global src_ip, dst_ip
src_ip = 1.1.1.1
dst_ip = 2.2.2.2
infile = "dump.pcap"

try:
    my_reader = PcapReader(infile)
    my_send(my_reader)
except IOError:
    print "Failed reading file %s contents" % infile
    sys.exit(1)

def my_send(rd, count=100):
    pkt_cnt = 0
    p_out = []

    for p in rd:
        pkt_cnt += 1
        np = p.payload
        np[IP].dst = dst_ip
        np[IP].src = src_ip
        del np[IP].chksum
        p_out.append(np)
        if pkt_cnt % count == 0:
            send(PacketList(p_out))
            p_out = []

    # Send remaining in final batch
    send(PacketList(p_out))
    print "Total packets sent %d" % pkt_cn

0
为了得到正确的校验和,我还需要添加del p[UDP].chksum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接