【问题标题】:python中的多线程http服务器
【发布时间】: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


【解决方案1】:

您仅为 run_server 方法创建了线程。为了在多线程上运行 sniff 函数,您还必须为 sniff 函数创建一个线程。

您可以从本文档中了解基本的多线程: https://www.geeksforgeeks.org/multithreading-python-set-1/

【讨论】:

  • 我不能从他的主线程运行嗅探 - 没有为它创建一个新线程?
  • 你必须为每个函数创建一个线程,然后是 start 和 join 方法。然后它将是一个多线程应用程序。在您的情况下,与您创建守护线程的方式相同,同样您必须为嗅探功能复制相同的内容。
猜你喜欢
  • 2014-04-20
  • 2020-12-11
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
相关资源
最近更新 更多