【问题标题】:Python port forwarding/multiplexing serverPython端口转发/多路复用服务器
【发布时间】:2009-12-09 14:37:30
【问题描述】:

我想让服务器侦听 UDP 端口 162(SNMP 陷阱),然后将此流量转发给多个客户端。同样重要的是源端口和地址保持不变(地址欺骗)。

我想最好的工具是 TwistedScapy 或者香草套接字, 只有我在 Twisted 的文档中找不到关于源地址欺骗/伪造的任何内容。

有什么解决办法吗?

编辑:添加赏金,mybe 有什么 iptables 解决方案?

【问题讨论】:

    标签: python networking iptables packet-mangling


    【解决方案1】:

    我对扭曲或 scapy 感到不舒服,但使用 vanilla python 套接字来做到这一点非常简单。这样做的一个额外好处是它将更加便携。此代码适用于我的有限测试:

    #!/usr/bin/python
    from socket import *
    bufsize = 1024 # Modify to suit your needs
    targetHost = "somehost.yourdomain.com"
    listenPort = 1123
    
    def forward(data, port):
        print "Forwarding: '%s' from port %s" % (data, port)
        sock = socket(AF_INET, SOCK_DGRAM)
        sock.bind(("localhost", port)) # Bind to the port data came in on
        sock.sendto(data, (targetHost, listenPort))
    
    def listen(host, port):
        listenSocket = socket(AF_INET, SOCK_DGRAM)
        listenSocket.bind((host, port))
        while True:
            data, addr = listenSocket.recvfrom(bufsize)
            forward(data, addr[1]) # data and port
    
    listen("localhost", listenPort)
    

    【讨论】:

    • 有一件事我忘了在问题陈述的第一部分输入我需要来自原始服务器的源地址和端口(所以实际上服务器需要伪造源地址),socket 可以这样做吗?
    • 不,不,它不能。我认为您在这里尝试解决的问题可能会通过一些 iptables 规则得到更好的解决。为什么你想用 python 来做呢?
    • 顺便说一句,如果你可以伪造带有扭曲的数据包头,我会感到非常惊讶; scapy 可能是你最好的选择。我去看看有多难。
    • 好的,scapy 会做的。如果可以的话,我今晚会试着写一个例子。
    • iptables 实际上我对 iptables 不是很熟悉,所以我需要学习新技能才能在 iptables 中做到这一点,因为我更多地发现了 Python,所以我决定学习如何在 Python 中做到这一点,并且现在我做得不好;)
    【解决方案2】:

    接受的答案对我不起作用,我最终使用A simple TCP redirector in python

    #!/usr/bin/env python
    
    import socket
    import threading
    import select
    import sys
    
    terminateAll = False
    
    class ClientThread(threading.Thread):
        def __init__(self, clientSocket, targetHost, targetPort):
            threading.Thread.__init__(self)
            self.__clientSocket = clientSocket
            self.__targetHost = targetHost
            self.__targetPort = targetPort
    
        def run(self):
            print "Client Thread started"
    
            self.__clientSocket.setblocking(0)
    
            targetHostSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            targetHostSocket.connect((self.__targetHost, self.__targetPort))
            targetHostSocket.setblocking(0)
    
            clientData = ""
            targetHostData = ""
            terminate = False
            while not terminate and not terminateAll:
                inputs = [self.__clientSocket, targetHostSocket]
                outputs = []
    
                if len(clientData) > 0:
                    outputs.append(self.__clientSocket)
    
                if len(targetHostData) > 0:
                    outputs.append(targetHostSocket)
    
                try:
                    inputsReady, outputsReady, errorsReady = select.select(inputs, outputs, [], 1.0)
                except Exception, e:
                    print e
                    break
    
                for inp in inputsReady:
                    if inp == self.__clientSocket:
                        try:
                            data = self.__clientSocket.recv(4096)
                        except Exception, e:
                            print e
    
                        if data != None:
                            if len(data) > 0:
                                targetHostData += data
                            else:
                                terminate = True
                    elif inp == targetHostSocket:
                        try:
                            data = targetHostSocket.recv(4096)
                        except Exception, e:
                            print e
    
                        if data != None:
                            if len(data) > 0:
                                clientData += data
                            else:
                                terminate = True
    
                for out in outputsReady:
                    if out == self.__clientSocket and len(clientData) > 0:
                        bytesWritten = self.__clientSocket.send(clientData)
                        if bytesWritten > 0:
                            clientData = clientData[bytesWritten:]
                    elif out == targetHostSocket and len(targetHostData) > 0:
                        bytesWritten = targetHostSocket.send(targetHostData)
                        if bytesWritten > 0:
                            targetHostData = targetHostData[bytesWritten:]
    
            self.__clientSocket.close()
            targetHostSocket.close()
            print "ClienThread terminating"
    
    if __name__ == '__main__':
        if len(sys.argv) != 5:
            print 'Usage:\n\tpython SimpleTCPRedirector <host> <port> <remote host> <remote port>'
            print 'Example:\n\tpython SimpleTCPRedirector localhost 8080 www.google.com 80'
            sys.exit(0)     
    
        localHost = sys.argv[1]
        localPort = int(sys.argv[2])
        targetHost = sys.argv[3]
        targetPort = int(sys.argv[4])
    
        serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        serverSocket.bind((localHost, localPort))
        serverSocket.listen(5)
        print "Waiting for client..."
        while True:
            try:
                clientSocket, address = serverSocket.accept()
            except KeyboardInterrupt:
                print "\nTerminating..."
                terminateAll = True
                break
            ClientThread(clientSocket, targetHost, targetPort).start()
    
        serverSocket.close()
    

    【讨论】:

      【解决方案3】:

      一种不同但相关的转发端口解决方案,而不是多路复用(不回答具体问题,但希望匹配相关问题 - 这至少是我一直在寻找的):

      http://www.linux-support.com/cms/forward-network-connections-with-python/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-04
        • 1970-01-01
        • 2022-11-22
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        • 1970-01-01
        • 2012-11-14
        相关资源
        最近更新 更多