【问题标题】:How can I create a non-http proxy with Twisted如何使用 Twisted 创建非 http 代理
【发布时间】:2011-06-08 07:05:26
【问题描述】:

如何使用 Twisted 创建非 http 代理。相反,我想为完全由二进制数据组成的泰拉瑞亚协议做这件事。我看到他们有一个用于 HTTP 连接的内置代理,但是这个应用程序需要更像一个入口点,它被转发到一个集合服务器(几乎就像 IRC 上的 BNC)。 我不知道如何从一个连接中读取数据并将其发送到另一个连接。

我已经尝试使用套接字来完成这项任务,但是阻塞的 recv 和 send 方法不能很好地工作,因为两个连接需要同时处于活动状态。

【问题讨论】:

  • 您是否正在尝试构建负载均衡器?
  • @tMC 否。所有连接都将转到一台服务器。有点像 IRC 上的 BNC。当 BNC 连接到 IRC 服务器时,您连接到 BNC。如果您失去与 BNC 的连接,您可以重新连接而不会丢失会话。
  • 您希望代理什么协议?
  • 您应该更具体地提出这个问题:您想要哪些协议?到目前为止,您尝试过什么?
  • @tMC 我希望代理泰拉瑞亚(游戏)协议。它由二进制数据组成。

标签: python twisted


【解决方案1】:

在 Twisted 中有几种不同的方法可以创建代理。基本技术是建立在对等互连之上的,通过在两个不同的端口上采用两种不同的协议,并以某种方式将它们粘合在一起,以便它们可以相互交换数据。

最简单的代理是端口转发器。 Twisted 附带一个端口转发器实现,请参阅http://twistedmatrix.com/documents/current/api/twisted.protocols.portforward.html 了解(未充分记录的)类ProxyClientProxyServer,尽管http://twistedmatrix.com/trac/browser/tags/releases/twisted-11.0.0/twisted/protocols/portforward.py 的实际源代码可能更便于阅读。从那里,我们可以看到 Twisted 中代理的基本技术:

def dataReceived(self, data):
    self.peer.transport.write(data)

当代理协议接收到数据时,它会将数据发送给另一端的对等方。而已!非常简单。当然,您通常需要一些额外的设置...让我们看看我之前写过的几个代理。

这是 Darklight 的代理,我编写的一个小型点对点系统。它正在与后端服务器通信,并且如果数据与预定义的标头不匹配,它只想代理数据。您可以看到它使用ProxyClientFactory 和端点(基本上是花哨的ClientCreator)来启动代理,当它接收到数据时,它有机会在继续之前对其进行检查,以保持代理或切换协议。

class DarkServerProtocol(Protocol):
    """
    Shim protocol for servers.
    """

    peer = None
    buf = ""

    def __init__(self, endpoint):
        self.endpoint = endpoint
        print "Protocol created..."

    def challenge(self, challenge):
        log.msg("Challenged: %s" % challenge)
        # ...omitted for brevity...
        return is_valid(challenge)

    def connectionMade(self):
        pcf = ProxyClientFactory()
        pcf.setServer(self)
        d = self.endpoint.connect(pcf)
        d.addErrback(lambda failure: self.transport.loseConnection())

        self.transport.pauseProducing()

    def setPeer(self, peer):
        # Our proxy passthrough has succeeded, so we will be seeing data
        # coming through shortly.
        log.msg("Established passthrough")
        self.peer = peer

    def dataReceived(self, data):
        self.buf += data

        # Examine whether we have received a challenge.
        if self.challenge(self.buf):
            # Excellent; change protocol.
            p = DarkAMP()
            p.factory = self.factory
            self.transport.protocol = p
            p.makeConnection(self.transport)
        elif self.peer:
            # Well, go ahead and send it through.
            self.peer.transport.write(data)

这是一段相当复杂的代码,它需要两个StatefulProtocols 并将它们相当有力地粘合在一起。这是来自一个 VNC 代理(准确地说是 https://code.osuosl.org/projects/twisted-vncauthproxy),它需要它的协议在准备好加入之前做很多预认证工作。这种代理是最坏的情况;为了速度,您不想与通过代理的数据进行交互,但您需要事先进行一些设置。

def start_proxying(result):
    """
    Callback to start proxies.
    """

    log.msg("Starting proxy")
    client_result, server_result = result
    success = True
    client_success, client = client_result
    server_success, server = server_result

    if not client_success:
        success = False
        log.err("Had issues on client side...")
        log.err(client)

    if not server_success:
        success = False
        log.err("Had issues on server side...")
        log.err(server)

    if not success:
        log.err("Had issues connecting, disconnecting both sides")
        if not isinstance(client, Failure):
            client.transport.loseConnection()
        if not isinstance(server, Failure):
            server.transport.loseConnection()
        return

    server.dataReceived = client.transport.write
    client.dataReceived = server.transport.write
    # Replay last bits of stuff in the pipe, if there's anything left.
    data = server._sful_data[1].read()
    if data:
        client.transport.write(data)
    data = client._sful_data[1].read()
    if data:
        server.transport.write(data)

    server.transport.resumeProducing()
    client.transport.resumeProducing()
    log.msg("Proxying started!")

所以,既然我已经解释过了...

我还写了 Bravo。如http://www.bravoserver.org/。所以我对 Minecraft 有所了解,因此也对泰拉瑞亚有所了解。您可能想要解析通过代理的数据包,因此您的实际代理可能开始看起来像这样,但随着您开始了解您正在代理的数据,它会迅速发展。希望这足以让您入门!

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多