Существует несколько различных способов создания прокси в Twisted. Базовый метод основан на пиринге: он использует два разных протокола на двух разных портах и каким-то образом склеивает их, чтобы они могли обмениваться данными друг с другом.
Простейший прокси-сервер - это перенаправитель портов. Скрученные корабли с реализацией порт-экспедитора, см. 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, маленькой одноранговой системы, которую я написал. Он общается с внутренним сервером и хочет только прокси-данные, если данные не соответствуют предопределенному заголовку. Вы можете видеть, что он использует 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!")
Итак, теперь, когда я объяснил это ...
Я тоже написал Браво. Например, http://www.bravoserver.org/. Итак, я немного знаю о Minecraft и, следовательно, о Terraria. Возможно, вы захотите проанализировать пакеты, поступающие через ваш прокси-сервер с обеих сторон, поэтому ваш фактический прокси-сервер может выглядеть примерно так, но он будет быстро развиваться, когда вы начнете понимать данные, которые вы проксируете. Надеюсь, этого достаточно, чтобы вы начали!