我正在尝试使用python,scapy和netfilter队列来编写一个小的“防火墙”,该队列也处理没有已知到达顺序的碎片数据包。 所以我想把数据包保存在按IP头ID值排序的字典中,每个条目都是一个元组列表 - 数据包偏移量和netfilter队列数据包对象本身(所以当决定判决时我可以放弃或接受) 。 遇到的问题是在将新数据包附加到字典中的列表之后,看起来数据包的有效负载也附加到所有其他数据包。我已经查了一下,我认为它与不变性有关,但无法解决任何好的解决方案。 我是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')
任何帮助都会非常感激!
答案 0 :(得分:0)
事实证明,netfilter队列对象有效负载字段是指向网络驱动程序中缓冲区的指针。因此,接收缓冲区的每个数据包都会根据id继续附加有效负载。 我所做的是保持对原始有效载荷的scapy对象的引用并获得所需的结果。