使用 Paramiko 进行 DSA 密钥转发?

2024-05-23

我正在使用 Paramiko 在远程服务器上执行 bash 脚本。在其中一些脚本中,存在与其他服务器的 ssh 连接。如果我只使用 bash,不使用 Python,我的 DSA 密钥将被第一个远程服务器上的 bash 脚本转发并使用,以连接到第二个远程服务器。当我使用 Paramiko 时,情况并非如此。

重击示例:

Jean@mydesktop:~ & ssh root@firstserver
root@firstserver:~ # ssh root@secondserver hostname
secondserver.mydomain.org

使用帕拉米科:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import paramiko

class SSHSession:


    def __init__(self, server_address, user='root', port=22):
        self.connected = False
        self.server_address = server_address
        self.user           = user
        self.port           = port


    def connect(self, clear_channel=True):
        try:
            if self.server_address == None:
                raise ValueError('No hostname')
        except:
            raise ValueError('No hostname')
        else:
            try:
                self.ssh_client = paramiko.SSHClient()
                self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                self.ssh_client.connect(self.server_address, username=self.user)
                #self.transport = self.ssh_client.get_transport()
                #self.channel   = self.transport.open_forward_agent_channel()
                self.channel   = self.ssh_client.invoke_shell()
            except:
                self.connected = False
                return False
            else:
                self.connected = True
                return True

    def exec_command(self, command, newline='\r'):
        if not self.connected:
            raise Exception('Not connected')
        else:
            timeout = 31536000 # 365 days in seconds
            self.channel.settimeout(timeout)
            line_buffer    = ''
            channel_buffer = ''
            end_string     = 'CLIENT_EXPECT_CMD_OK'
            print('[SEND   ] >>', command)
            self.channel.send(command + ' ; echo ' + end_string + newline)
            while True:
                channel_buffer = self.channel.recv(1).decode('UTF-8')
                if len(channel_buffer) == 0:
                    raise Exception('connection lost with server: ' + self.server_address)
                    break 
                channel_buffer  = channel_buffer.replace('\r', '')
                if channel_buffer != '\n':
                    line_buffer += channel_buffer
                else:
                    if line_buffer == end_string:
                        break
                    print('[RECEIVE] <<', line_buffer)
                    line_buffer   = ''


    def disconnect(self):
        self.ssh_client.close()


    def __enter__(self):
        self.connect()
        return self


    def __exit__(self, _type, value, traceback):
        self.disconnect()


if __name__ == "__main__":
    server_address = 'firstserver'
    ssh_user       = 'root'
    with SSHSession(server_address) as ssh_session:
        ssh_session.exec_command('hostname')
        ssh_session.exec_command('ssh root@secondserver hostname')

输出是:

[SEND   ] >> hostname
[RECEIVE] << [root@firstserver ~]# hostname ; echo CLIENT_EXPECT_CMD_OK
[RECEIVE] << firstserver.mydomain.fr
[SEND   ] >> ssh root@secondserver hostname
[RECEIVE] << [root@firstserver ~]# ssh root@secondserver hostname ; echo CLIENT_EXPECT_CMD_OK
[RECEIVE] << Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

I tried:

self.transport = self.ssh_client.get_transport()
self.channel   = self.transport.open_forward_agent_channel()

代替 :

self.channel   = self.ssh_client.invoke_shell()

但后来我得到一个错误:

paramiko.ssh_exception.ChannelException: Administratively prohibited

有人知道这是否可能吗?我发现讨论表明就是这样,但我还没有找到如何做到这一点。


好的,现在可以了。我发现这些有用的帖子:

添加 paramiko ssh 代理转发(可选)#4100 https://github.com/ansible/ansible/pull/4100
open_forward_agent_channel 与 open_session #89 https://github.com/paramiko/paramiko/issues/89

最终代码是:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import paramiko

class SSHSession:


    def __init__(self, server_address, user='root', port=22):
        self.connected      = False
        self.server_address = server_address
        self.user           = user
        self.port           = port


    def connect(self):
        try:
            self.ssh_client = paramiko.SSHClient()
            self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.ssh_client.connect(self.server_address, username=self.user)
            self.transport     = self.ssh_client.get_transport()
            self.agent_channel = self.transport.open_session()
            self.agent_handler = paramiko.agent.AgentRequestHandler(self.agent_channel)
            self.channel       = self.ssh_client.invoke_shell()
        except:
            self.connected = False
        else:
            self.connected = True
        return self.connected

    def exec_command(self, command, newline='\r'):
        if not self.connected:
            raise Exception('Not connected')
        else:
            timeout = 31536000 # 365 days in seconds
            self.channel.settimeout(timeout)
            line_buffer    = ''
            channel_buffer = ''
            end_string     = 'CLIENT_EXPECT_CMD_OK'
            print('[SEND   ] >>', command)
            self.channel.send(command + ' ; echo ' + end_string + newline)
            while True:
                channel_buffer = self.channel.recv(1).decode('UTF-8')
                if len(channel_buffer) == 0:
                    raise Exception('connection lost with server: ' +     self.server_address)
                    break 
                channel_buffer  = channel_buffer.replace('\r', '')
                if channel_buffer != '\n':
                    line_buffer += channel_buffer
                else:
                    if line_buffer == end_string:
                        break
                    print('[RECEIVE] <<', line_buffer)
                    line_buffer   = ''


    def disconnect(self):
        self.ssh_client.close()


    def __enter__(self):
        self.connect()
        return self


    def __exit__(self, _type, value, traceback):
        self.disconnect()


if __name__ == "__main__":
    server_address = 'firstserver'
    ssh_user       = 'root'
    with SSHSession(server_address) as ssh_session:
        ssh_session.exec_command('hostname')
        ssh_session.exec_command('ssh root@secondserver hostname')

输出是:

[SEND   ] >> hostname
[RECEIVE] << [root@firstserver ~]# hostname ; echo CLIENT_EXPECT_CMD_OK
[RECEIVE] << firstserver.mydomain.fr
[SEND   ] >> ssh root@secondserver hostname
[RECEIVE] << [root@firstserver ~]# ssh root@secondserver hostname ; echo CLIENT_EXPECT_CMD_OK
[RECEIVE] << secondserver.mydomain.fr

启用代理转发的代码的重要部分是:

self.agent_channel = self.transport.open_session()
self.agent_handler = paramiko.agent.AgentRequestHandler(self.agent_channel)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Paramiko 进行 DSA 密钥转发? 的相关文章

随机推荐

  • Ruby 中的方法和属性有什么区别?

    你可以给我一个例子吗 属性只是一个捷径 如果你使用attr accessor要创建属性 Ruby 只需声明一个实例变量并为您创建 getter 和 setter 方法 既然你要求一个例子 class Thing attr accessor
  • 机器人探索算法

    我正在尝试为机器人设计一种算法 试图找到位于未知位置的旗帜 该旗帜位于一个包含障碍物的世界中 机器人的任务是夺取旗帜并将其带到他的基地 代表他的起始位置 机器人在每一步只能看到有限的邻域 他事先不知道世界是什么样子 但他有无限的内存来存储已
  • C# SmtpClient编程中如何设置带有中文的附件文件名?

    我的代码如下 ContentType ct new ContentType ct MediaType MediaTypeNames Application Octet ct Name 这是一个很长的中文文件名希望能用它在附件名中 Doc A
  • 只保留 A-Z 0-9 并使用 javascript 从字符串中删除其他字符

    我正在尝试验证字符串以使它们成为有效的网址 我只需要保留 A Z 0 9 并使用以下命令从字符串中删除其他字符javascript or jquery 例如 贝儿餐厅 我需要将其转换为 百丽餐厅 所以字符被删除 只保留 A Z a z 0
  • 格式说明符%02x

    我有一个简单的程序 include
  • 什么可能导致 Firefox 中出现此 HTML/CSS 渲染问题?

    款式 h2 color 71D0FF font size 11px font weight bold margin 0px 0px 5px 0px a box color FFFFFF important cursor pointer di
  • 如何防止输入文本中出现“后重音”

    我相信这是一个简单的问题 但在谷歌上搜索几个小时后我找不到任何答案 也许我无法在搜索中使用正确的单词 P 我有一个 javascript 方法 可以防止用户用数字以外的其他字符填充文本框 如下面的代码所示 它在 KeyDown 事件中使用
  • 对使用“new”创建的数组上“map”的行为感到困惑[重复]

    这个问题在这里已经有答案了 我对结果感到困惑mapping 使用创建的数组new function returnsFourteen return 14 var a new Array 4 gt undefined x 4 in Chrome
  • 如何在 Visual Studio 2013 中使用 Git 的外部 diff 工具?

    我找到了这个帖子 http architects dzone com articles how configure diff and merge这解释了如何让 Visual Studio 2013 在比较 Git 中的文件时使用内置 dif
  • 如何在 Makefile 中获取 make 命令的 pid?

    我想使用此构建特有的临时目录 如何在 Makefile 中获取 make 命令的 pid I tried TEMPDIR tmp myprog 但这似乎存储TEMPDIR as tmp myprog 然后将 eval 作为每个引用此命令的新
  • 如何过滤 Pandas GroupBy 对象并获取 GroupBy 对象?

    当对 Pandas groupby 操作的结果执行过滤时 它返回一个数据帧 但假设我想执行进一步的分组计算 我必须再次调用 groupby 这似乎有点绕 有更惯用的方法吗 EDIT 为了说明我在说什么 我们无耻地从 Pandas 文档中窃取
  • 创建上下文后将 jar 文件添加到 pyspark

    我正在笔记本上使用 pyspark 并且不处理 SparkSession 的创建 我需要加载一个包含一些我想在处理 rdd 时使用的函数的 jar 您可以使用 jars 轻松完成此操作 但在我的特定情况下我无法做到这一点 有没有办法访问sp
  • 未捕获的异常:数据表编辑器 - 不允许远程托管代码

    我正在尝试使用 Datatables 使用 datatableseditor 来实现 CRUD 操作 但是我收到错误消息 1 未捕获的异常 数据表编辑器 不允许远程托管代码 请参见http editor datatables net有关如何
  • 是否需要销毁运算符删除的形式才能真正销毁对象?

    C 20 添加了破坏形式operator delete区别于std destroying delete t范围 它导致delete表达式在调用之前不再销毁对象operator delete 目的是在显式调用对象的析构函数和释放内存之前 允许
  • 将图层坐标导出到 Excel 的脚本

    我找到了一个脚本 可以将我的图层坐标从 Photoshop CS5 导出到 XML 我希望这里有人可以帮助我编辑该脚本以将坐标记录到 xls 文件中 另外 如果可以将每个坐标放在单独的行上 那就太好了 下面是我想修改以满足我需要的脚本 Th
  • Ajax 内容和 jQuery 动画效果

    我正在尝试使用 jQuery 动画效果为 WordPress 帖子制作 Ajax 内容 问题是第一个动画 在本例中 fadeOut 工作正常 但第二个 FadeIn 或我尝试使用的任何动画效果没有对新内容生效 加载的内容只是出现 没有任何效
  • 增量后清除推送通知徽章

    我正在研究 iPhone 中的推送通知 当我收到推送通知时 它在我的应用程序图标上显示 1 下次显示 2 3 4 如果我打开应用程序 它是 0 下次它应该是 1 2 3 4 但它显示最后一个数字和 1 我想在打开应用程序后重置推送通知徽章
  • 刷新/重新加载 ASP.net 的副作用?

    我在 Web 和 ASP Net 开发方面相对较新 所以请耐心等待 在测试我们的网页的过程中 我注意到 如果用户单击 刷新 重新加载 并在 重新发送信息 对话框提示时单击 重试 则无论用户选择之前触发的最后一个事件如何到 刷新 随后将再次被
  • 无法解析“...”的依赖关系:无法解析项目:react-native-navigation

    问题描述 仔细按照中的说明进行操作后https wix github io react native navigation docs Installing https wix github io react native navigatio
  • 使用 Paramiko 进行 DSA 密钥转发?

    我正在使用 Paramiko 在远程服务器上执行 bash 脚本 在其中一些脚本中 存在与其他服务器的 ssh 连接 如果我只使用 bash 不使用 Python 我的 DSA 密钥将被第一个远程服务器上的 bash 脚本转发并使用 以连接