gpt4 book ai didi

python - 如何在 Paramiko 服务器中实现端口转发?

转载 作者:行者123 更新时间:2023-12-02 13:46:03 27 4
gpt4 key购买 nike

当您以 ssh user@host -L <local port>:<remote host>:<remote port> 身份运行 SSH 时,会发生“direct-tcpip”请求(通常称为端口转发)。然后尝试通过本地端口连接。

我正在尝试在自定义 SSH 服务器上实现 direct-tcpip,Paramiko 提供了 check_channel_direct_tcpip_requestServerInterface类以检查是否应允许“direct-tcpip”请求,可以按如下方式实现:

class Server(paramiko.ServerInterface):
# ...
def check_channel_direct_tcpip_request(self, chanid, origin, destination):
return paramiko.OPEN_SUCCEEDED

但是,当我使用上述 SSH 命令并通过本地端口连接时,没有任何 react ,可能是因为我需要自己实现连接处理。

阅读文档,似乎也只有在 OPEN_SUCCEDED 之后才打开 channel 已被退回。

返回后如何处理direct-tcpip 请求 OPEN_SUCCEEDED对于请求?

最佳答案

您确实需要设置自己的连接处理程序。这是一个解释我采取的步骤的冗长答案 - 如果您的服务器代码已经工作,您将不需要其中的一些。完整的运行服务器示例在这里:https://controlc.com/25439153

我使用了此处的 Paramiko 示例服务器代码 https://github.com/paramiko/paramiko/blob/master/demos/demo_server.py作为基础,并在其上植入了一些套接字代码。这没有任何错误处理、与线程相关的细节或任何其他“适当”的东西,但它允许您使用端口转发器。

这也有很多你不需要的东西,因为我不想开始整理一个虚拟的示例代码。对此表示歉意。

首先,我们需要转发器工具。这将创建一个线程来运行“隧道”转发器。这也回答了您从何处获得 channel 的问题。您accept()它来自传输,但您需要在转发器线程中执行此操作。正如您在 OP 中所述,check_channel_direct_tcpip_request() 中还没有它函数,但它最终将可供线程使用。

def tunnel(sock, chan, chunk_size=1024):
while True:
r, w, x = select.select([sock, chan], [], [])

if sock in r:
data = sock.recv(chunk_size)
if len(data) == 0:
break
chan.send(data)

if chan in r:
data = chan.recv(chunk_size)
if len(data) == 0:
break
sock.send(data)

chan.close()
sock.close()


class ForwardClient(threading.Thread):
daemon = True
# chanid = 0

def __init__(self, address, transport, chanid):
threading.Thread.__init__(self)

self.socket = socket.create_connection(address)
self.transport = transport
self.chanid = chanid

def run(self):
while True:
chan = self.transport.accept(10)
if chan == None:
continue

print("Got new channel (id: %i).", chan.get_id())

if chan.get_id() == self.chanid:
break

peer = self.socket.getpeername()
try:
tunnel(self.socket, chan)
except:
pass

回到示例服务器代码。与示例代码不同,您的服务器类需要将传输作为参数:
class Server(paramiko.ServerInterface):
# 'data' is the output of base64.b64encode(key)
# (using the "user_rsa_key" files)
data = (
b"AAAAB3NzaC1yc2EAAAABIwAAAIEAyO4it3fHlmGZWJaGrfeHOVY7RWO3P9M7hp"
b"fAu7jJ2d7eothvfeuoRFtJwhUmZDluRdFyhFY/hFAh76PJKGAusIqIQKlkJxMC"
b"KDqIexkgHAfID/6mqvmnSJf0b5W8v5h2pI/stOSwTQ+pxVhwJ9ctYDhRSlF0iT"
b"UWT10hcuO4Ks8="
)
good_pub_key = paramiko.RSAKey(data=decodebytes(data))

def __init__(self, transport):
self.transport = transport
self.event = threading.Event()

然后您将覆盖相关方法并在那里创建转发器:
def check_channel_direct_tcpip_request(self, chanid, origin, destination):
print(chanid, origin, destination)
f = ForwardClient(destination, self.transport, chanid)
f.start()

return paramiko.OPEN_SUCCEEDED

您需要将传输参数添加到服务器类的创建中:
t.add_server_key(host_key)
server = Server(t)

此示例服务器要求您在名为 test_rsa.key 的目录中具有 RSA 私钥。在那里创建任何 RSA key ,您不需要它,但我没有费心从代码中剥离它的使用。

然后您可以运行您的服务器(在端口 2200 上运行)并发出
ssh -p 2200 -L 2300:www.google.com:80  robey@localhost

(密码是 foo)

现在当你尝试
telnet localhost 2300

在那里输入一些东西,你会得到谷歌的回复。

关于python - 如何在 Paramiko 服务器中实现端口转发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62125669/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com