Paramiko request_port_forward 带或不带处理程序

问题描述 投票:0回答:1

总长:

使用回调时无法从传入的 paramiko 端口转发连接读取数据。 请参阅此要点进行演示:
https://gist.github.com/tatome/0d3e6479f35b25bbb31c9f94610eab6b

详细问题:

这里有一个示例脚本,演示如何使用 paramiko 设置反向隧道。 该脚本请求端口转发,然后在主线程中保持

accept

连接,并将处理这些连接委托给另一个线程:

transport.request_port_forward("", server_port)
while True:
    chan = transport.accept(1000)
    if chan is None:
        continue
    thr = threading.Thread(
        target=handler, args=(chan, remote_host, remote_port)
    )

不幸的是,使用这种方法,我们不知道传入连接访问哪个端口,因此我们不能在我们不同对待的不同服务器端口上拥有多个隧道。

但是,我们可以将

handler

参数传递给

request_port_forward
handler
确实会获取客户端访问的主机名和端口:
def handler(channel, source_address, target_address):
    target_host, target_port = target_address
    ...

client.get_transport().request_port_forward('', port, handler)

问题是:

由于某种原因,通过 transport.accept() 检索的通道和传递给

handler
的通道对我来说表现不同。
当我这样做时:

client.connect( 'localhost', 22, username=USER, look_for_keys=True ) def handler(channel, source_address, target_address): print("Selecting...") selects = select.select([channel],[],[]) print("Selected: " + str(selects)) transport = client.get_transport() p = transport.request_port_forward('', 30000) print(p) channel = transport.accept(1000) handler(channel, None, None)

然后,在外壳上:

wget localhost:30000

我明白了:

30000 Selecting... Selected: ([<paramiko.Channel 0 (open) window=2097152 in-buffer=130 -> <paramiko.Transport at 0x43b80fd0 (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>], [], [])

如果我将处理程序传递给 
request_port_forward

,但是,像这样:

def handler(channel, source_address, target_address):
    print("Selecting...")
    selects = select.select([channel],[],[])
    print("Selected: " + str(selects))

transport = client.get_transport()
transport.request_port_forward('', 30000, handler)

我明白了:

Selecting...

当我调试脚本时,它会停在显示 
selects = select.select([channel],[],[])

的行中。

wget

表示它发送了 HTTP 请求,但我的脚本从未从连接中读取任何内容。

问题:

我做错了什么?
  • 为什么
  • select.select([channel])
  • 会执行其他操作,具体取决于它是由
    transport.accept()
    返回还是传递给处理程序?
    如何对多个不同的反向隧道使用相同的传输?
python ssh paramiko ssh-tunnel
1个回答
0
投票
handler

在主线程上调用,而在第二个代码中,

handler
在另一个线程上调用。我不认为
Paramiko 是线程安全的
我会尝试的是仅使用

handler

来通知主线程循环(在

request_port_forward
之后)隧道已打开并让它处理它。
快速而肮脏的代码(只是为了测试我是否正确)

tunnel_channel = None def handler(channel, source_address, target_address): global tunnel_channel print("Tunnel opened.") tunnel_channel = channel transport = client.get_transport() transport.request_port_forward('', 30000, handler) while True: if tunnel_channel != None: print("Selecting...") selects = select.select([channel],[],[]) print("Selected: " + str(selects)) time.sleep(1)

© www.soinside.com 2019 - 2024. All rights reserved.