簡體   English   中英

如何使用 Twisted 創建非 http 代理

[英]How can I create a non-http proxy with Twisted

如何使用 Twisted 創建非 http 代理。 相反,我想為完全由二進制數據組成的泰拉瑞亞協議做這件事。 我看到他們有一個用於 HTTP 連接的內置代理,但是這個應用程序需要更像一個被轉發到集合服務器的入口點(幾乎就像 IRC 上的 BNC)。 我不知道如何從一個連接中讀取數據並將其發送到另一個連接。

我已經嘗試使用套接字來執行此任務,但是阻塞的 recv 和 send 方法不能很好地工作,因為兩個連接需要同時處於活動狀態。

在 Twisted 中有幾種不同的方法可以創建代理。 基本技術是建立在對等之上的,通過在兩個不同的端口上采用兩種不同的協議,並以某種方式將它們粘合在一起,以便它們可以相互交換數據。

最簡單的代理是端口轉發器。 Twisted ships with a port-forwarder implementation, see http://twistedmatrix.com/documents/current/api/twisted.protocols.portforward.html for the (underdocumented) classes ProxyClient and ProxyServer , although the actual source at 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 的代理。 它正在與后端服務器通信,並且如果數據與預定義的 header 不匹配,它只想代理數據。 您可以看到它使用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)

這是一段相當復雜的代碼,它需要兩個StatefulProtocol並將它們相當有力地粘合在一起。 這是來自一個 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 有所了解,因此也對泰拉瑞亞有所了解。 您可能想要解析通過代理的數據包,因此您的實際代理可能開始看起來像這樣,但隨着您開始了解您正在代理的數據,它會迅速發展。 希望這足以讓您入門!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM