前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python:指定 SSH-ED25519 公钥算法访问 OpenSSH-server

Python:指定 SSH-ED25519 公钥算法访问 OpenSSH-server

作者头像
运维开发王义杰
发布2024-07-20 10:59:28
860
发布2024-07-20 10:59:28
举报
文章被收录于专栏:运维开发王义杰

随着 OpenSSH 的不断更新和安全性的提升,最新版本的 OpenSSH 服务器(如 openssh-server-9.8p1-1)逐步减少了对某些旧公钥算法的支持,转而仅支持更安全的算法如 ssh-ed25519。这在增强安全性的同时,也给一些依赖旧公钥算法的工具和脚本带来了兼容性问题。本文将探讨如何解决 Python 脚本在这种环境下无法正常连接服务器的问题。

问题背景

在最新版本的 OpenSSH 服务器中,默认配置仅支持 ssh-ed25519 公钥算法。这导致了许多工具和脚本,尤其是基于 Python 的 Paramiko 库无法正常工作,因为它们默认使用的公钥算法可能不包括 ssh-ed25519。以下是一个常见的错误信息:

代码语言:javascript
复制


Exception (client): Unable to agree on a pubkey algorithm for signing a 'ssh-rsa' key!
解决方案

要解决这个问题,我们需要显式地指定 Paramiko 使用 ssh-ed25519 算法。以下是详细步骤和代码示例。

1. 更新 Paramiko 和加密库

首先,确保 Paramiko 和其依赖库(如 Cryptography)是最新的。使用以下命令进行更新:

代码语言:javascript
复制

bash
pip install --upgrade paramiko cryptography
2. 创建和配置 SSH 客户端

在 Python 脚本中,使用 Paramiko 创建 SSH 客户端,并配置其使用 ssh-ed25519 公钥算法进行连接。以下是完整的代码示例:

代码语言:javascript
复制

python
import paramiko

def create_ssh_client(server, port, user, password):
    """创建SSH客户端并连接到服务器"""
    ssh = paramiko.SSHClient()
    ssh.load_system_host_keys()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    # 配置公钥算法
    ssh.connect(server, port=port, username=user, password=password, allow_agent=False, look_for_keys=False)
    
    # 获取 transport 并设置公钥算法
    transport = ssh.get_transport()
    transport.get_security_options().key_types = ['ssh-ed25519']
    
    return ssh

# 使用示例
server = '10.0.0.16'
port = 22
user = 'root'
password = '+~qCw?Ao2i08mqTp'

ssh_client = create_ssh_client(server, port, user, password)

# 示例:上传文件
sftp = ssh_client.open_sftp()
sftp.put('upload_file.py', '/tmp/upload_file.py')
sftp.close()

ssh_client.close()
3. 验证和调试连接

为了确保连接成功,可以启用调试模式查看详细的连接过程:

代码语言:javascript
复制

bash
ssh -vvv root@10.0.0.16

这将输出详细的调试信息,有助于识别和解决潜在的问题。

4. 工具开发

我们可以扩展该脚本以支持命令行参数输入主机信息、区分执行命令和上传文件的功能。下面是一个完整的解决方案,包括处理命令行参数的代码,并区分执行命令和上传文件的逻辑。

完整代码:

代码语言:javascript
复制

python
import paramiko
import argparse
import sys

def create_ssh_client(server, port, user, password):
    """创建SSH客户端并连接到服务器"""
    ssh = paramiko.SSHClient()
    ssh.load_system_host_keys()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    # 配置公钥算法
    ssh.connect(server, port=port, username=user, password=password, allow_agent=False, look_for_keys=False)
    
    # 获取 transport 并设置公钥算法
    transport = ssh.get_transport()
    transport.get_security_options().key_types = ['ssh-ed25519']
    
    return ssh

def upload_file(ssh_client, local_path, remote_path):
    """上传文件到远程服务器"""
    sftp = ssh_client.open_sftp()
    sftp.put(local_path, remote_path)
    sftp.close()

def execute_command(ssh_client, command):
    """在远程服务器上执行命令"""
    stdin, stdout, stderr = ssh_client.exec_command(command)
    print(stdout.read().decode())
    print(stderr.read().decode())

def main():
    parser = argparse.ArgumentParser(description='SSH 文件上传和命令执行工具')
    parser.add_argument('server', help='服务器地址')
    parser.add_argument('port', type=int, help='服务器端口')
    parser.add_argument('user', help='用户名')
    parser.add_argument('password', help='密码')
    parser.add_argument('--upload', nargs=2, metavar=('local_path', 'remote_path'), help='上传文件')
    parser.add_argument('--command', help='执行远程命令')

    args = parser.parse_args()

    try:
        ssh_client = create_ssh_client(args.server, args.port, args.user, args.password)

        if args.upload:
            local_path, remote_path = args.upload
            upload_file(ssh_client, local_path, remote_path)
        elif args.command:
            execute_command(ssh_client, args.command)
        else:
            print("请提供 --upload 或 --command 参数以执行相应的操作。")

        ssh_client.close()
    except Exception as e:
        print(f"连接或操作过程中发生错误: {e}")
        sys.exit(1)

if __name__ == '__main__':
    main()

使用说明

上传文件:

代码语言:javascript
复制

bash
python script.py <server> <port> <user> <password> --upload <local_path> <remote_path>

例如:

代码语言:javascript
复制

bash
python script.py 10.0.0.16 22 root '+~qCw?Ao2i08mqTp' --upload upload_file.py /tmp/upload_file.py

执行命令:

代码语言:javascript
复制

bash
python script.py <server> <port> <user> <password> --command "<command>"

例如:

代码语言:javascript
复制

bash
python script.py 10.0.0.16 22 root '+~qCw?Ao2i08mqTp' --command "ls -l /tmp"

该脚本可以灵活地根据命令行参数来处理不同的操作需求,包括上传文件和执行命令。这样不仅增强了脚本的功能性,还提高了使用的便利性,适应了最新版本 OpenSSH 服务器的安全要求。

总结

通过上述步骤,我们能够解决由于 OpenSSH 仅支持 ssh-ed25519 公钥算法而导致的 Python 脚本无法连接的问题。确保使用最新版本的 Paramiko 和正确配置公钥算法,可以保证脚本在更安全的 SSH 环境中正常运行。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维开发王义杰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题背景
  • 解决方案
  • 1. 更新 Paramiko 和加密库
  • 2. 创建和配置 SSH 客户端
  • 3. 验证和调试连接
  • 4. 工具开发
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档