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服务器端扩展的缺失。
尝试rsa-sha2-*完全禁用 Paramiko 端:
ssh_client.connect(\n server, username=ssh_user, key_filename=ssh_keypath,\n disabled_algorithms=dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"]))\nRun Code Online (Sandbox Code Playgroud)\n(请注意,无需指定port=22,因为这是默认值)
我发现了相关的 Paramiko 问题:
\n RSA 密钥身份验证从 paramiko 2.9.x 客户端到 dropbear 服务器失败
虽然它指的是Paramiko 2.9.0 更改日志,这似乎暗示该行为是故意的:
\n\n\n当服务器不发送 时
\nserver-sig-algs,Paramiko 将尝试上面列表中的第一个算法。因此,连接到旧服务器的客户端应使用disabled_algorithms关闭 SHA2。
从2.9.2开始,Paramiko 会说:
\n\n\nDEB [20220113-14:46:13.882] thr=1 paramiko.transport:服务器未发送 server-sig-algs 列表;默认为我们的第一个首选算法 (\'rsa-sha2-512\')
\n
\nDEB [20220113-14:46:13.882] thr=1 paramiko.transport: 注意:您可以使用 \'disabled_algorithms\' SSHClient/Transport init kwarg 来禁用该算法或其他算法(如果您的服务器不支持它们)!
强制性警告:请勿使用\xe2\x80\x93这样做您将失去针对MITM 攻击的AutoAddPolicy保护。正确的解决方案请参见Paramiko“未知服务器”。
您等待命令完成并读取其输出的代码也有缺陷。请参阅等待完成使用 Python Paramiko 执行的命令。对于大多数目的来说,这get_pty=True也不是一个好主意。