python Python端口转发/多路复用服务器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1874331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 23:15:14  来源:igfitidea点击:

Python port forwarding/multiplexing server

pythonnetworkingiptablespacket-mangling

提问by Ib33X

I would like to make server that listen on UDP port 162 (SNMP trap) and then forwards this traffic to multiple clients. Also important is that the source port & address stays same (address spoofing).

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

I guess that best tool for this would be Twistedor Scapyor maybe vanilla sockets, only I can't find anything in the documentation for Twisted about source address spoofing/forging.

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

Any solution for this?

有什么解决办法吗?

Edit:added bounty, mybe any solution with iptables?

编辑:增加了赏金,我的 iptables 有什么解决方案吗?

回答by Benson

I am not comfortable with twisted or scapy, but it's quite straightforward to do this with vanilla python sockets. An extra advantage of that is that it will be even more portable. This code works in my limited tests:

我对 Twisted 或 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)

回答by Luke Stanley

A different but sort of related solution to forwarding ports, not multiplexing (not answering the specific question but hopefully matching related ones - this is what I was looking for at least):

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

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

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

回答by CONvid19

The accepted answer didn't work for me and I end up using A simple TCP redirector in python:

接受的答案对我不起作用,我最终在 python 中使用了一个简单的 TCP 重定向器

#!/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()