问题描述
我正在使用 Twisted 编写自定义 SSL 代理。我一直遇到一个经常发生的问题,但我无法弄清楚问题是什么。
当我尝试通过 registerProducer 函数将客户端传输连接到服务器的传输时,与twisted.protocols.portforward 函数完全一样,我不断收到此错误。
File "/opt/Memory/Mobile/Proxy/forwarder.py",line 40,in connectionMade
self.peer.transport.registerProducer(self.transport,True)
File "/usr/lib/python3.9/site-packages/twisted/protocols/tls.py",line 602,in registerProducer
self.transport.registerProducer(producer,True)
File "/usr/lib/python3.9/site-packages/twisted/internet/_newtls.py",line 233,in registerProducer
FileDescriptor.registerProducer(self,producer,streaming)
File "/usr/lib/python3.9/site-packages/twisted/internet/abstract.py",line 104,in registerProducer
raise RuntimeError(
builtins.RuntimeError: Cannot register producer <twisted.protocols.tls._ProducerMembrane object at 0x7fb5799f0910>,because producer <twisted.protocols.tls._ProducerMembrane object at 0x7fb579b474c0> was never unregistered.
这是我从 Twisted 继承的类?
from twisted.internet import reactor
from twisted.internet import ssl
from twisted.protocols import portforward
from twisted.internet import protocol
from twisted.python import log
import sys
##SSLProxy base class that will be inherited
class SSLProxy(protocol.Protocol):
noisy = True
peer = None
def setPeer(self,peer):
#log.msg("SSLProxy.setPeer")
self.peer = peer
def connectionLost(self,reason):
#log.msg("SSLProxy.connectionLost")
if self.peer is not None:
self.peer.transport.loseConnection()
self.peer = None
elif self.noisy:
log.msg("Unable to connect to peer: {}".format(reason))
def dataReceived(self,data):
#log.msg("SSLProxy.dataReceived")
if self.peer is not None:
self.peer.transport.write(data)
##Foward data from Proxy to => Remote Server
class SSLProxyClient(SSLProxy):
def connectionMade(self):
#log.msg("SSLProxyClient.connectionMade")
self.peer.setPeer(self)
self.transport.registerProducer(self.peer.transport,True)
self.peer.transport.registerProducer(self.transport,True)
# We're connected,everybody can read to their hearts content.
self.peer.transport.resumeProducing()
class SSLProxyClientFactory(protocol.ClientFactory):
protocol = SSLProxyClient
def setServer(self,server):
#log.msg("SSLProxyClientFactory.setServer")
self.server = server
def buildProtocol(self,*args,**kw):
#log.msg("SSLProxyClientFactory.buildProtocol")
prot = protocol.ClientFactory.buildProtocol(self,**kw)
prot.setPeer(self.server)
return prot
def clientConnectionFailed(self,connector,reason):
#log.msg("SSLProxyClientFactory.clientConnectionFailed")
self.server.transport.loseConnection()
class SSLProxyServer(SSLProxy):
clientProtocolFactory = SSLProxyClientFactory
reactor = None
def connectionMade(self):
log.msg("SSLProxyServer.connectionMade")
#Get Current SSL Context
ssl_context = self.transport._tlsConnection.get_context()
#Hack to get SNI to do two functions in diffrent classes
ssl_context._finishSNI = self.SNICallback
def SNICallback(self,connection):
#log.msg("SSLProxyServer.SNICallback: {}".format(connection))
#print(connection.get_context().new_host)
self.transport.pauseProducing()
#self.transport.transport.pauseProducing()
#print(dir())
self.dst_host,self.dst_port = connection.get_context().new_host
#Setup Clients
self.client = self.clientProtocolFactory()
self.client.setServer(self)
#Start stuff
log.msg('Redirecting to {}:{}'.format(self.dst_host,self.dst_port))
if self.reactor is None:
self.reactor = reactor
log.msg("Making Connection to Dest Server: {}:{}".format(self.dst_host,self.dst_port))
self.reactor.connectSSL(self.dst_host,self.dst_port,self.client,ssl.ClientContextFactory())
#self.transport.resumeProducing()
#Client -> Proxy
def dataReceived(self,data):
log.msg("SSLProxyServer.dataReceived: {}".format(data))
#Call Inherited Function
super().dataReceived(data)
class SSLProxyFactory(protocol.Factory):
"""Factory for port forwarder."""
protocol = SSLProxyServer
def __init__(self):
super().__init__()
#log.msg("SSLProxyFactory.__init__")
def sslToSSL(localport,remotehost,remoteport,serverContextFactory):
log.msg("SSL on localhost:{} forwarding to SSL {}:{}".format(localport,remoteport))
return reactor.listenSSL(localport,SSLProxyFactory(),serverContextFactory)
任何指导将不胜感激。
解决方法
我发现,如果您只是取消注册当前的 Producer,您就可以注册新的 Producer。
##Foward data from Proxy to => Remote Server
class SSLProxyClient(SSLProxy):
def connectionMade(self):
#log.msg("SSLProxyClient.connectionMade")
self.peer.setPeer(self)
self.transport.registerProducer(self.peer.transport,True)
self.peer.transport.unregisterProducer()
self.peer.transport.registerProducer(self.transport,True)
# We're connected,everybody can read to their hearts content.
self.peer.transport.resumeProducing()