Как я могу создать не HTTP-прокси с Twisted

1

Как создать прокси-сервер non- с помощью Twisted. Вместо этого я хотел бы сделать это для протокола Terraria, который полностью состоит из двоичных данных. Я вижу, что они имеют built- в прокси для HTTP-соединений, но это приложение должно действовать скорее как точка входа, которая перенаправляется на заданный сервер (почти как BNC на IRC). Я не могу понять, как считывать данные с одного соединения и отправлять его другому соединению.

Я уже пробовал использовать сокет для этой задачи, но методы блокировки recv и send не работают хорошо, так как два соединения должны быть в одно и то же время.

  • 0
    Вы пытаетесь построить балансировщик нагрузки?
  • 0
    @tMC tMC Нет. Все соединения будут идти к одному серверу. Вроде как BNC на IRC. Вы подключаетесь к BNC, пока он подключается к IRC-серверу. Если вы потеряете соединение с BNC, вы можете просто восстановить соединение, не теряя сеанс.
Показать ещё 9 комментариев
Теги:
twisted

1 ответ

6
Лучший ответ

Существует несколько способов создания прокси в Twisted. Основная методика построена на пиринге, используя два разных протокола, на двух разных портах и ​​как-то склеивая их вместе, чтобы они могли обмениваться данными друг с другом.

Простейшим прокси является port- forwarder. Скрученные корабли с реализацией экспедитора port-, см. http://twistedmatrix.com/documents/current/api/twisted.protocols.portforward.html для (недокументированных) классов ProxyClient и ProxyServer, хотя фактический источник в 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, маленькой peer- to- одноранговой системы, которую я написал. Он обращается к серверу backend, и он хочет только прокси-данные, если данные не соответствуют предопределенному заголовку. Вы можете видеть, что он использует 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, чтобы быть точным), который нуждается в протоколах, чтобы сделать много аутентификационных материалов pre-, прежде чем они будут готовы к объединению. Этот вид прокси - худший случай; для скорости вы не хотите взаимодействовать с данными, проходящими через прокси-сервер, но вам нужно заранее выполнить некоторую настройку.

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 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!")

Итак, теперь, когда я объяснил, что...

Я также написал Браво. Как в http://www.bravoserver.org/. Поэтому я немного знаю о Minecraft и, таким образом, о Террарии. Вероятно, вы захотите проанализировать пакеты, проходящие через ваш прокси-сервер с обеих сторон, поэтому ваш фактический прокси-сервер может начать выглядеть так, но он быстро изменится, когда вы начнете понимать данные, которые вы проксируете. Надеюсь, этого достаточно, чтобы вы начали!

  • 0
    Этот простой рецепт является еще одним отличным примером не-протокола конкретного прокси. code.activestate.com/recipes/...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню