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
Python port forwarding/multiplexing server
提问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.
我想最好的工具是Twisted或Scapy或者可能是 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()