gpt4 book ai didi

python - 使用 paramiko 进行 x11 转发

转载 作者:太空狗 更新时间:2023-10-29 17:04:46 28 4
gpt4 key购买 nike

我正在尝试使用 paramiko 运行一个应该能够打开 X 窗口的命令。我正在使用的脚本如下所示:

import paramiko                                    

ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect('192.168.122.55', username='user', password='password')
transport = ssh_client.get_transport()
session = transport.open_session()

session.request_x11()
stdin = session.makefile('wb')
stdout = session.makefile('rb')
stderr = session.makefile_stderr('rb')
session.exec_command('env; xterm')
transport.accept()

print 'Exit status:', session.recv_exit_status()
print 'stdout:\n{}'.format(stdout.read())
print 'stderr:\n{}'.format(stderr.read())
session.close()

不幸的是,当我运行上面的脚本时,我得到了这个输出:

Exit status: 1
stdout:
SHELL=/bin/bash
XDG_SESSION_COOKIE=8025e1ba5e6c47be0d2f3ad6504a25ee-1347286654.617967-1932974971
SSH_CLIENT=192.168.122.1 58654 22
USER=user
MAIL=/var/mail/user
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
PWD=/home/user
LANG=en_US.UTF-8
SHLVL=1
HOME=/home/user
LOGNAME=user
SSH_CONNECTION=192.168.122.1 58654 192.168.122.55 22
DISPLAY=localhost:10.0
_=/usr/bin/env

stderr:
xterm: Xt error: Can't open display: localhost:10.0

如果我在终端中运行以下命令:

ssh -X user@192.168.122.55 'env; xterm'

然后我得到了相同的环境变量(虽然有些端口发生了变化),所以我会说我的环境是正确的。但是,我仍然缺少使 paramiko 与 x11 转发一起工作的东西。

我尝试过的一些事情是:

  • request_x11 中使用 handler 参数:除了打印值外,我没有比使用默认处理程序更进一步。
  • request_x11 中使用 auth_cookie 参数:尝试根据 xauth list 输出对正在使用的 cookie 值进行硬编码。这样做的想法是避免根据 paramiko 本身的文档字符串可能发生的问题:

If you omit the auth_cookie, a new secure random 128-bit value will be generated, used, and returned. You will need to use this value to verify incoming x11 requests and replace them with the actual local x11 cookie (which requires some knoweldge of the x11 protocol).

我还能做些什么来让它工作或解决问题吗?

注意:这已被问及:

  • superuser : 唯一的响应指向我已经尝试使用但无济于事的 request_x11 文档。
  • stackoverflow : 接受的响应建议使用 handler 参数,但这是错误的。
  • github : 超过一年没有提供答案。

最佳答案

看了paramiko的代码,发现paramiko只是实现了一种建立x11 channel 的方式。它不会将 channel 连接到本地 x11 显示器。那留给你了。

这是我刚刚编写的一个小实现:

#!/usr/bin/env python

import os
import select
import sys

import paramiko
import Xlib.support.connect as xlib_connect


local_x11_display = xlib_connect.get_display(os.environ['DISPLAY'])
local_x11_socket = xlib_connect.get_socket(*local_x11_display[:3])


ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect('server', username='username', password='password')
transport = ssh_client.get_transport()
session = transport.open_session()
session.request_x11(single_connection=True)
session.exec_command('xterm')
x11_chan = transport.accept()

session_fileno = session.fileno()
x11_chan_fileno = x11_chan.fileno()
local_x11_socket_fileno = local_x11_socket.fileno()

poller = select.poll()
poller.register(session_fileno, select.POLLIN)
poller.register(x11_chan_fileno, select.POLLIN)
poller.register(local_x11_socket, select.POLLIN)
while not session.exit_status_ready():
poll = poller.poll()
if not poll: # this should not happen, as we don't have a timeout.
break
for fd, event in poll:
if fd == session_fileno:
while session.recv_ready():
sys.stdout.write(session.recv(4096))
while session.recv_stderr_ready():
sys.stderr.write(session.recv_stderr(4096))
if fd == x11_chan_fileno:
local_x11_socket.sendall(x11_chan.recv(4096))
if fd == local_x11_socket_fileno:
x11_chan.send(local_x11_socket.recv(4096))

print 'Exit status:', session.recv_exit_status()
while session.recv_ready():
sys.stdout.write(session.recv(4096))
while session.recv_stderr_ready():
sys.stdout.write(session.recv_stderr(4096))
session.close()

一些注意事项:

  • 我正在使用 python-Xlib 中的一些辅助函数。这是 Xlib 的纯 Python 实现。有关安装的详细信息,请参阅此问题:How do you install Python Xlib with pip?

  • 我如何实现它的一些细节让我相信它只适用于 1 x11 连接(因此 session.request_x11(single_connection=True)。)我想继续努力让它处理多个连接,但这将不得不等待另一天。

  • 此代码实质上使用 select.poll 以异步方式将以下 channel /套接字连接在一起。 :

    • session.stdout -> sys.stdout
    • session.stderr -> sys.stderr
    • x11channel -> local_x11_socket
    • local_x11_socket -> x11channel
  • paramiko 模块向logging 模块输出大量有用的调试信息。您可以通过配置日志记录模块来查看:

    import logging
    logging.basicConfig(level=logging.DEBUG)

关于python - 使用 paramiko 进行 x11 转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12354047/

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