使用pysftp验证主机密钥

我正在使用pysftp编写程序,它想要验证SSH主机密钥对 C:\Users\JohnCalvin\.ssh\known_hosts .

使用PuTTY,终端程序将其保存到Registry [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys] .

如何调和pysftp和PuTTY之间的区别?

我的代码是:

import pysftp as sftp

def push_file_to_server():
    s = sftp.Connection(host='138.99.99.129', username='root', password='*********')
    local_path = "testme.txt"
    remote_path = "/home/testme.txt"

    s.put(local_path, remote_path)
    s.close()

push_file_to_server()

我收到的错误响应是:

E:\ Program Files(x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __ . py:61:UserWarning:无法从C:\ Users \ JohnCalvin.ssh \ known_hosts加载HostKeys . 您需要显式加载HostKeys(cnopts.hostkeys.load(filename))或disableHostKey检查(cnopts.hostkeys = None) . warnings.warn(wmsg,UserWarning)Traceback(最近一次调用最后一次):文件“E:\ OneDrive \ Python \ GIT \ DigitalCloud \ pysftp_tutorial.py”,第14行,在push_file_to_server()文件“E:\ OneDrive \ Python \ GIT \ DigitalCloud \ pysftp_tutorial.py“,第7行,在push_file_to_server中s = sftp.Connection(host ='138.99.99.129',用户名='root',密码='********')文件”E :\ Program Files(x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __ . py“,第132行,在init self._tconnect ['hostkey'] = self._cnopts.get_hostkey(host)文件”E:\ Program Files (x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __ . py“,第71行,在get_hostkey中引发SSHException(”找不到主机%s的主机密钥 . “%host)paramiko.ssh_exception.SSHException:主机138.99没有主机密钥 . 99.129找到了 . 在以下情况中忽略异常:> Traceback(最近一次调用最后一次):文件“E:\ Program Files(x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __ . py”,第1013行,在del self.close()文件中“E :\ Program Files(x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __ . py“,第784行,如果self._sftp_live关闭:AttributeError:'Connection'对象没有属性'_sftp_live'

回答(5)

2 years ago

以下解决方案适合我:

import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None   
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
    sftp.put(local_path, remote_path)

你可以在这里找到更多信息:https://stackoverflow.com/a/38355117/1060738

2 years ago

Do not set cnopts.hostkeys = None (作为最受欢迎的答案显示),除非您不关心安全性 . 这样做会失去对Man-in-the-middle attacks的保护 .


使用 CnOpts.hostkeys (返回HostKeys)来管理可信主机密钥 .

cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('known_hosts')

with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:

其中 known_hosts 包含服务器公钥[s],格式如下:

example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...

如果您不想使用外部文件,也可以使用

from base64 import decodebytes
# ...

keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB..."""
key = paramiko.RSAKey(data=decodebytes(keydata))
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add('example.com', 'ssh-rsa', key)

with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:

以这种格式检索主机密钥的简单方法是使用OpenSSH ssh-keyscan

$ ssh-keyscan example.com
# example.com SSH-2.0-OpenSSH_5.3
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...

您还可以使应用程序自动执行相同操作:
Use Paramiko AutoAddPolicy with pysftp
(它会自动将新主机的主机密钥添加到 known_hosts ,但对于已知的主机密钥,它不会接受更改的密钥)


虽然绝对安全,但如果您没有受到攻击,则不应该远程检索主机密钥,因为您无法确定 .

看我的文章Where do I get SSH host key fingerprint to authorize the server?
它适用于我的WinSCP SFTP客户端,但大多数信息一般都有效 .


如果只需使用其指纹验证主机密钥,请参阅Python - pysftp / paramiko - Verify host key using its fingerprint .

2 years ago

尝试使用0.2.8版本的pysftp库 . $ pip uninstall pysftp && pip install pysftp==0.2.8

试试这个:

try:
    ftp = pysftp.Connection(host, username=user, password=password)
 except:
    print("Couldn't connect to ftp")
    return False

为什么这个?基本上是0.2.9的pysftp错误所有细节https://github.com/Yenthe666/auto_backup/issues/47

2 years ago

嗨,如果我理解你,我们会遇到同样的问题 . 那么请检查一下pysftp版本're using. If it'的最新版本是0.2.9降级到0.2.8 . 看一下这个 . https://github.com/Yenthe666/auto_backup/issues/47

2 years ago

首先使用使用known_hosts文件的Windows ssh客户端连接到服务器 . PuTTy将数据存储在Windows注册表中,但是OpenSSH使用known_hosts文件,并在连接后在其中添加条目 . 该文件的默认位置是%USERPROFILE%.ssh . 我希望这有帮助