重建碎片化的 IP 数据包 - python
Reconstructing fragmented IP packets - python
我正在尝试使用 python、scapy 和 netfilter queue 编写一个小的 "firewall",它还可以处理没有已知到达顺序的碎片数据包。
所以我想将数据包保存在按 IP header ID 值排序的字典中,每个条目都是一个元组列表 - 数据包偏移量和 netfilter queue 数据包 object 本身(所以当判决作出时,我可以放弃或接受)。
我遇到的问题是在将新数据包附加到字典中的列表后,看起来数据包的有效负载也附加到所有其他数据包。我查了一下,我认为它与不变性有关,但没有任何好处 solution\explanation 。
我是 python 的新手,非常希望得到一些指导。
代码:
def update_fragmented_lists(scapy_packet, pkt):
current_dict = pkt_dict[scapy_packet[IP].id]
if len(current_dict) < 4:
current_dict.append((scapy_packet[IP].frag, pkt))
else:
for frag, waiting_pkt in current_dict:
waiting_pkt.drop()
del(pkt_dict[scapy_packet[IP].id])
def reconstruct_packet(packet_id):
curr_dict = pkt_dict[packet_id]
curr_dict = sorted(curr_dict, key=get_key)
print(curr_dict)
if IP(curr_dict[-1][1].get_payload()).flags == 1:
return None
last_off = 0
http_req = ""
for (offset, pkt) in curr_dict:
scapy_packet = IP(pkt.get_payload())
if offset*8 == last_off:
http_req += scapy_packet[Raw].load
last_off += len(scapy_packet[Raw].load)
else:
http_req = None
break
return http_req
def handle_packet(pkt):
scapy_packet = IP(pkt.get_payload())
packet_id = scapy_packet[IP].id
if (scapy_packet[IP].flags == 1) or (scapy_packet[IP].flags == 0 and scapy_packet[IP].frag != 0):
update_fragmented_lists(scapy_packet, pkt)
http_req = reconstruct_packet(packet_id)
if http_req is not None:
if check_forbidden_suffix(http_req):
for offset, fragmented_pkt in pkt_dict[packet_id]:
fragmented_pkt.accept()
else:
for offset, fragmented_pkt in pkt_dict[packet_id]:
fragmented_pkt.drop()
pkt_dict = defaultdict(list)
nfqueue = NetfilterQueue()
nfqueue.bind(1, handle_packet)
try:
nfqueue.run()
except KeyboardInterrupt:
os.system('iptables -F')
os.system('iptables -X')
任何帮助将不胜感激!
事实证明,netfilter queue object payload字段是一个指向网络驱动中缓冲区的指针。因此,每个接收到缓冲区的数据包都会根据 id 不断附加有效负载。
我所做的是继续参考我投射的原始有效载荷的 scapy 对象并获得所需的结果。
我正在尝试使用 python、scapy 和 netfilter queue 编写一个小的 "firewall",它还可以处理没有已知到达顺序的碎片数据包。 所以我想将数据包保存在按 IP header ID 值排序的字典中,每个条目都是一个元组列表 - 数据包偏移量和 netfilter queue 数据包 object 本身(所以当判决作出时,我可以放弃或接受)。 我遇到的问题是在将新数据包附加到字典中的列表后,看起来数据包的有效负载也附加到所有其他数据包。我查了一下,我认为它与不变性有关,但没有任何好处 solution\explanation 。 我是 python 的新手,非常希望得到一些指导。 代码:
def update_fragmented_lists(scapy_packet, pkt):
current_dict = pkt_dict[scapy_packet[IP].id]
if len(current_dict) < 4:
current_dict.append((scapy_packet[IP].frag, pkt))
else:
for frag, waiting_pkt in current_dict:
waiting_pkt.drop()
del(pkt_dict[scapy_packet[IP].id])
def reconstruct_packet(packet_id):
curr_dict = pkt_dict[packet_id]
curr_dict = sorted(curr_dict, key=get_key)
print(curr_dict)
if IP(curr_dict[-1][1].get_payload()).flags == 1:
return None
last_off = 0
http_req = ""
for (offset, pkt) in curr_dict:
scapy_packet = IP(pkt.get_payload())
if offset*8 == last_off:
http_req += scapy_packet[Raw].load
last_off += len(scapy_packet[Raw].load)
else:
http_req = None
break
return http_req
def handle_packet(pkt):
scapy_packet = IP(pkt.get_payload())
packet_id = scapy_packet[IP].id
if (scapy_packet[IP].flags == 1) or (scapy_packet[IP].flags == 0 and scapy_packet[IP].frag != 0):
update_fragmented_lists(scapy_packet, pkt)
http_req = reconstruct_packet(packet_id)
if http_req is not None:
if check_forbidden_suffix(http_req):
for offset, fragmented_pkt in pkt_dict[packet_id]:
fragmented_pkt.accept()
else:
for offset, fragmented_pkt in pkt_dict[packet_id]:
fragmented_pkt.drop()
pkt_dict = defaultdict(list)
nfqueue = NetfilterQueue()
nfqueue.bind(1, handle_packet)
try:
nfqueue.run()
except KeyboardInterrupt:
os.system('iptables -F')
os.system('iptables -X')
任何帮助将不胜感激!
事实证明,netfilter queue object payload字段是一个指向网络驱动中缓冲区的指针。因此,每个接收到缓冲区的数据包都会根据 id 不断附加有效负载。 我所做的是继续参考我投射的原始有效载荷的 scapy 对象并获得所需的结果。