【发布时间】:2022-01-23 11:16:00
【问题描述】:
我正在尝试在 python 中构建一个 HTTP 服务器, 嗅探数据包并将它们发送到另一个接口。 服务器可以通过 POST http 请求获取路由路径。 所以我需要服务器将并行嗅探包并监听 http 请求。 这是我的代码:
from scapy.all import *
from scapy.layers.inet import IP, UDP
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
from socketserver import ThreadingMixIn
import threading
ROUTING_LIST = []
INTERFACE_TO_SNIFF = 'vEthernet'
PORT = 80
class Route:
def __init__(self):
self.first_IP_src = ""
self.first_port_src = ""
self.first_IP_dst = ""
self.first_port_dst = ""
self.first_iface = ""
self.second_IP_src = ""
self.second_port_src = ""
self.second_IP_dst = ""
self.second_port_dst = ""
self.second_iface = ""
class Server(BaseHTTPRequestHandler):
# POST echoes the message adding a JSON field
def do_POST(self):
# read the message and convert it into a python dictionary
length = int(self.headers['Content-length'])
message = self.rfile.read(length)
routing_dict = json.loads(message, strict=False)
if add_routing_http(routing_dict) is True:
print("New Routing received:")
print("{" + "\n".join("{!r}: {!r},".format(k, v) for k, v in routing_dict.items()) + "}")
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(
("POST routing request received! now we have " + str(len(ROUTING_LIST)) + " routes").encode("utf8"))
def run_server():
global PORT
server_address = ('', PORT)
httpd = HTTPServer(server_address, Server)
print('Starting httpd on port %d...' % PORT)
httpd.serve_forever()
def add_routing_local(first_IP_src, first_port_src, first_IP_dst, first_port_dst, first_iface,
second_IP_src, second_port_src, second_IP_dst, second_port_dst, second_iface):
global ROUTING_LIST
temp = Route()
temp.first_IP_src = first_IP_src
temp.first_port_src = first_port_src
temp.first_IP_dst = first_IP_dst
temp.first_port_dst = first_port_dst
temp.first_iface = first_iface
temp.second_IP_src = second_IP_src
temp.second_port_src = second_port_src
temp.second_IP_dst = second_IP_dst
temp.second_port_dst = second_port_dst
temp.second_iface = second_iface
ROUTING_LIST.append(temp)
def add_routing_http(routing_dict):
global ROUTING_LIST
temp = Route()
temp.first_IP_src = routing_dict.get('firstIpSrc')
temp.first_port_src = routing_dict.get('firstPortSrc')
temp.first_IP_dst = routing_dict.get('firstIpDst')
temp.first_port_dst = routing_dict.get('firstPortDst')
temp.first_iface = routing_dict.get('firstIface')
temp.second_IP_src = routing_dict.get('secondIpSrc')
temp.second_port_src = routing_dict.get('secondPortSrc')
temp.second_IP_dst = routing_dict.get('secondIpDst')
temp.second_port_dst = routing_dict.get('secondPortDst')
temp.second_iface = routing_dict.get('secondIface')
ROUTING_LIST.append(temp)
return True
def packets_filter(packet):
return IP in packet and UDP in packet and Raw in packet
def match_packet(packet, routing):
match = True
if routing.first_IP_src != '' and packet[IP].src != routing.first_IP_src:
return False
if routing.first_IP_dst != '' and packet[IP].dst != routing.first_IP_dst:
return False
if routing.first_port_src != '' and packet[UDP].sport != routing.first_port_src:
return False
if routing.first_port_dst != '' and packet[UDP].dport != routing.first_port_dst:
return False
if routing.first_iface != '' and packet.sniffed_on is not None and routing.first_iface != packet.sniffed_on:
return False
return True
def handle_packet(packet):
global ROUTING_LIST
for routing in ROUTING_LIST:
if match_packet(packet, routing) is True:
new_packet = packet.copy()
new_packet[IP].src = routing.second_IP_src
new_packet[IP].dst = routing.second_IP_dst
new_packet[UDP].sport = routing.second_port_src
new_packet[UDP].dport = routing.second_port_dst
new_packet.show()
sendp(new_packet) # sendp(new_packet, iface=routing.second_iface)iface='eth0'
return
def main():
daemon = threading.Thread(name='daemon_server', target=run_server, args=())
daemon.setDaemon(True) # Set as a daemon so it will be killed once the main thread is dead.
daemon.start()
print("start sniffing")
sniff(lfilter=packets_filter, prn=handle_packet) # sniff(lfilter=packets_filter, prn=handle_packet, iface=INTERFACE_TO_SNIFF)
if __name__ == "__main__":
main()
简而言之 - 我希望 main 函数同时运行这两个函数:run_server、sniff。如果我尝试只运行其中一个 - 两者都很好。 在这段代码中,只有 run_server 起作用,但嗅探不起作用。 怎么了? 谢谢你
【问题讨论】:
-
您只为 run_server 方法创建了线程。为了在多线程上运行嗅探函数,您还必须为嗅探函数创建一个线程。
标签: python multithreading http scapy