我正在尝试开始使用 Paramiko 库,但是当我尝试连接以下简单程序时,该库就会抛出异常:
import paramiko
ssh = paramiko.SSHClient()
ssh.connect('127.0.0.1', username='boatzart', password='mypassword')
我得到的错误是:
Traceback (most recent call last):
File "test.py", line 6, in <module>
ssh.connect('127.0.0.1')
File "build/bdist.macosx-10.7-intel/egg/paramiko/client.py", line 316, in connect
File "build/bdist.macosx-10.7-intel/egg/paramiko/client.py", line 85, in missing_host_key
paramiko.SSHException: Unknown server 127.0.0.1
无论我尝试使用哪个服务器,都会发生这种情况。
我遇到了同样的问题,这是适合我的解决方案:
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('127.0.0.1', username=username, password=password)
stdin, stdout, stderr = client.exec_command('ls -l')
这是为了设置连接到系统或本地 HostKeys 对象中没有主机密钥的服务器时要使用的策略。默认策略是拒绝所有未知服务器(使用 RejectPolicy)。您可以替换 AutoAddPolicy 或编写自己的策略类。
更多详细信息请参见paramiko api 文档。希望这有帮助。
之后您可以保存到其他密钥文件中以供下次使用,如下所示。
ssh.get_host_keys().save('/some/file/path')
您始终可以按如下方式从文件加载。
ssh.load_host_keys('/some/file/path')
正确的方法是:
在调用 HostKeys.add
之前,在
SSHClient.get_host_keys
返回的实例上调用
connect
,将可信密钥传递给它。
from base64 import decodebytes
# ...
keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB..."""
key = paramiko.RSAKey(data=decodebytes(keydata))
client.get_host_keys().add('example.com', 'ssh-rsa', key)
根据实际的密钥类型,您可能需要使用
ECDSAKey
或 Ed25519Key
而不是 RSAKey
。
要了解如何获取代码中使用的密钥,请参阅我的回答:
使用 pysftp 验证主机密钥。
如果您只知道指纹,请参阅:
Python - pysftp / paramiko - 使用指纹验证主机密钥
或者使用
ssh
加载已缓存的主机密钥(例如通过 OpenSSH 命令行
client.load_system_host_keys()
)。
或者您至少可以缓存第一次尝试时的主机密钥,以确保它将来不会更改。
为此,请在 SSHClient.load_host_keys
之前使用
connect
。它使 Paramiko 自动将新的主机密钥添加到文件中(与 AutoAddPolicy
组合使用)。
引发异常是因为您缺少主机密钥,相当神秘的“未知服务器”是线索 - 因为异常是从
missing_host_key
引发的
试试这个:
import paramiko
paramiko.util.log_to_file('ssh.log') # sets up logging
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('127.0.0.1', username=username, password=password)
stdin, stdout, stderr = client.exec_command('ls -l')
我遇到了这个问题,想在这里发布解决方法。问题确实是 ssh 服务器发送 ecdsa 密钥,而 paramiko(尚)不支持这些密钥。在我的 debian Wheezy 系统上,我通过注释掉 /etc/ssh/sshd_config 中的一行来禁用 ecdsa:
# 主机密钥 /etc/ssh/ssh_host_ecdsa_key
重新启动 sshd,又回到使用 RSA。我的known_hosts 文件中有一些ecdsa 密钥,因此我只是将其删除以重置,然后手动登录以重新创建密钥。从那时起,paramiko 通过 RSA 主机密钥检查按照预期完美工作。
我遇到了这个错误:我可以从 shell 连接,但 paramiko 说“未知服务器 workdevel114”。
known_hosts 中有两个类似的条目:
user@host> grep workdevel114 ~/.ssh/known_hosts
workdevel114 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC8qGbuI1BaBodi7sKWLfV8Eh+De80Th7HFLD4WiJWo57THl0Q+QcopUaU3pF....
user@host> grep I1BaBodi7sKWLfV8Eh+De80Th7HFLD4WiJWo57THl0Q+QcopUaU3pF ~/.ssh/known_hosts
workdevel114 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC8qGbuI1BaBodi7sK...
|1|f/auQ9nY5dFbVtOdY3ocjtVO9dM=|esvazUDTT3VIcLk9DxmPI6FZt1s= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC8qGbuI1BaBodi7sKWLfV8Eh+De80Th7HFLD4...
秒条目 (|1|....) 似乎让 paramiko 感到困惑。我猜这与这张票有关:https://github.com/paramiko/paramiko/issues/67
我通过添加这一行解决了这个问题:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
但是在这种情况下,这会禁用 ssh 协议的主机检查:Paramiko 认为主机密钥未知,但它是已知的。已知的密钥将被忽略。我不在乎,因为在我的环境中中间人攻击不太可能发生。
paraiko-版本:1.7.7.1-1ubuntu1
我尝试使用上下文管理器将 Martin Prikryl 的部分响应合并到一个类中。
或者您至少可以缓存第一次尝试时的主机密钥,以确保它将来不会更改。 为此,请在连接之前使用
.load_host_keys 。它使 Paramiko 自动将新的主机密钥添加到文件中(与SSHClient
组合时)。AutoAddPolicy
import paramiko
from paramiko import client, sftp_client
class SFTP:
sftp: sftp_client.SFTPClient
ssh: client.SSHClient
host: str
user: str
password: str
def __init__(self, host: str, user: str, password: str):
self.host = host
self.user = user
self.password = password
def __enter__(self) -> sftp_client.SFTPClient:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.load_system_host_keys()
ssh.connect(self.host, username=self.user, password=self.password)
self.ssh = ssh
sftp = ssh.open_sftp()
self.sftp = sftp
return sftp
def __exit__(self, exc, _, __) -> bool:
if exc is None:
self.sftp.close()
self.ssh.close()
return True
raise exc
示例:
with SFTP('host', 'user', 'password') as sftp:
...