我正在尝试使用scapy发送以pcap格式记录的流量。目前,我卡在了去除原始Ether层上。该流量是在另一台主机上捕获的,我基本上需要更改IP和Ether层的源和目标地址。我设法替换IP层并重新计算校验和,但是Ether层让我很困扰。
有没有人有从应用更改后的IP和Ether层(src和dst)重发捕获文件中的数据包的经验?此外,这个捕获文件相当大,几GB左右,使用scapy处理如此大的流量会有什么性能方面的问题吗?
查看此示例
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
评论:
sniff(offline="filename")
来读取数据包,也可以使用prn参数,例如:sniff(offline="filename",prn=My_Function)
。在这种情况下,My_Functions将应用于每个被嗅探到的数据包。ip="1.1.1.1"
等,如上所示。map
的建议,我不确定这是否会提高性能,因为scapy的send/sendp方法接收一个数据包列表作为参数,并且在函数内部它们有一个for
循环(__gen_send
函数)。因此,也许通过逐个调用map
而不是直接将数据包列表传递给send/sendp所获得的优势,在内部的for
循环中就会失去。 - newlogip_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)
使用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
del p[UDP].chksum
。
tcpreplay
能否处理更改源地址和目的地址的请求功能?我查看了一下,但未能找到此功能,这就是我来到此页面的原因。 - Vercingatorixtcprewrite
工具的伪NAT选项(例如-S
)和0.0.0.0/0:<ip>/32
(如果您想将所有源地址更改为<ip>
)来首先转换文件,然后使用tcpreplay
工具进行回放。 - Vercingatorix