[英]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.