Paramiko 身份验证失败,并显示“同意​​‘rsa-sha2-512’公钥算法”(以及 sshd 日志中的“不支持的公钥算法:rsa-sha2-512”)

don*_*ior 22 python linux ssh paramiko

我有一个在 CentOS Linux 7.7 上运行的 Python 3 应用程序,对远程主机执行 SSH 命令。它工作正常,但今天我在对“新”远程服务器(基于 RHEL 6.10 的服务器)执行命令时遇到了一个奇怪的错误:

遇到 RSA 密钥,预期的 OPENSSH 密钥

从系统 shell 执行相同的命令(当然使用相同的私钥)效果非常好。

在远程服务器上,我发现/var/log/secure当使用 Python(使用 Paramiko)从源服务器发出 SSH 连接和命令时,sshd 会抱怨不支持的公钥算法:

userauth_pubkey:不支持的公钥算法:rsa-sha2-512

请注意,具有更高 RHEL/CentOS(如 7.x)的目标服务器不会遇到此问题。

看起来 Paramiko 在与远程服务器协商时选择/提供了错误的算法,而相反 SSH shell 在此“旧”目标服务器的上下文中正确执行协商。如何让Python程序按预期工作?

Python代码

import paramiko
import logging

ssh_user = "my_user"
ssh_keypath = "/path/to/.ssh/my_key.rsa"
server = "server.tld"

ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh_client.connect(server,port=22,username=ssh_user, key_filename=ssh_keypath)  

# SSH command
cmd = "echo TEST : $(hostname)"

stdin, stdout, stderr = ssh_client.exec_command(cmd, get_pty=True)
exit_code = stdout.channel.recv_exit_status() 

cmd_raw_output = stdout.readlines()
out = "".join(cmd_raw_output)
out_msg = out.strip()  

# Ouput (logger code omitted)
logger.debug(out_msg)

if ssh_client is not None:
    ssh_client.close()
Run Code Online (Sandbox Code Playgroud)

等效的 Shell 命令

ssh -i /path/to/.ssh/my_key.rsa my_user@server.tld "echo TEST : $(hostname)"   
Run Code Online (Sandbox Code Playgroud)

Paramiko 日志(调试)

import paramiko
import logging

ssh_user = "my_user"
ssh_keypath = "/path/to/.ssh/my_key.rsa"
server = "server.tld"

ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh_client.connect(server,port=22,username=ssh_user, key_filename=ssh_keypath)  

# SSH command
cmd = "echo TEST : $(hostname)"

stdin, stdout, stderr = ssh_client.exec_command(cmd, get_pty=True)
exit_code = stdout.channel.recv_exit_status() 

cmd_raw_output = stdout.readlines()
out = "".join(cmd_raw_output)
out_msg = out.strip()  

# Ouput (logger code omitted)
logger.debug(out_msg)

if ssh_client is not None:
    ssh_client.close()
Run Code Online (Sandbox Code Playgroud)

外壳命令日志

ssh -i /path/to/.ssh/my_key.rsa my_user@server.tld "echo TEST : $(hostname)"   
Run Code Online (Sandbox Code Playgroud)

Mar*_*ryl 36

我认为,这是 Paramiko 中的一个错误。它无法正确处理server-sig-algs服务器端扩展的缺失。

\n

尝试rsa-sha2-*完全禁用 Paramiko 端:

\n
ssh_client.connect(\n  server, username=ssh_user, key_filename=ssh_keypath,\n  disabled_algorithms=dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"]))\n
Run Code Online (Sandbox Code Playgroud)\n

(请注意,无需指定port=22,因为这是默认值)

\n

我发现了相关的 Paramiko 问题:
\n RSA 密钥身份验证从 paramiko 2.9.x 客户端到 dropbear 服务器失败

\n

虽然它指的是Paramiko 2.9.0 更改日志,这似乎暗示该行为是故意的:

\n
\n

当服务器不发送 时server-sig-algs,Paramiko 将尝试上面列表中的第一个算法。因此,连接到旧服务器的客户端应使用disabled_algorithms关闭 SHA2。

\n
\n
\n

从2.9.2开始,Paramiko 会说:

\n
\n

DEB [20220113-14:46:13.882] thr=1 paramiko.transport:服务器未发送 server-sig-algs 列表;默认为我们的第一个首选算法 (\'rsa-sha2-512\')
\nDEB [20220113-14:46:13.882] thr=1 paramiko.transport: 注意:您可以使用 \'disabled_algorithms\' SSHClient/Transport init kwarg 来禁用该算法或其他算法(如果您的服务器不支持它们)!

\n
\n
\n

强制性警告:请勿使用\xe2\x80\x93这样做您将失去针对MITM 攻击的AutoAddPolicy保护。正确的解决方案请参见Paramiko“未知服务器”

\n
\n

您等待命令完成并读取其输出的代码也有缺陷。请参阅等待完成使用 Python Paramiko 执行的命令。对于大多数目的来说,这get_pty=True也不是一个好主意。

\n

  • This saved us after several hours of debugging. Your syntax for disabled_algorithms does NOT match paramiko documentation but it works, i.e. disabled_algorithms=dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"])). From paramiko (https://www.paramiko.org/changelog.html): "Specifically, you need to specify disabled_algorithms={'keys': ['rsa-sha2-256', 'rsa-sha2-512']} in either SSHClient or Transport. See below for details on why." (3认同)
  • 对我来说,禁用“keys”(如 paramiko 的变更日志中所建议的)不起作用,只有在禁用“pubkeys”之后我才能连接。感谢您的提示! (3认同)