使用pysftp验证主机密钥

Gab*_*los 53 python ssh pysftp

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

使用PuTTY,终端程序将其保存到注册表[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()
Run Code Online (Sandbox Code Playgroud)

我收到的错误响应是:

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'

Noa*_*led 65

以下解决方案适合我:

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

您可以在此处找到更多信息:https: //stackoverflow.com/a/38355117/1060738

  • 快速说明.如果路径中有一个空的known_hosts文件,则CnOpts()将失败. (5认同)
  • 请参阅[我的解决方案答案](http://stackoverflow.com/a/43389508/850848)。 (4认同)
  • 是的,这就是我最终解决问题的方法.但这样做只会忽略主机密钥.我希望能够通过读取实际密钥来保留安全性(如果可能). (2认同)

Mar*_*ryl 51

使用cnopts.hostkeys = None(返回CnOpts.hostkeys)管理可信主机密钥.

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

with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
Run Code Online (Sandbox Code Playgroud)

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

example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
Run Code Online (Sandbox Code Playgroud)

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

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:
Run Code Online (Sandbox Code Playgroud)

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

$ ssh-keyscan example.com
# example.com SSH-2.0-OpenSSH_5.3
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
Run Code Online (Sandbox Code Playgroud)

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


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

请参阅我的文章在哪里获取SSH主机密钥指纹以授权服务器?
它适用于我的WinSCP SFTP客户端,但大多数信息一般都有效.


如果您只需要使用其指纹验证主机密钥,请参阅Python - pysftp/paramiko - 使用其指纹验证主机密钥.


Yug*_*hra 11

使用 pysftp.CnOpts() 和主机密钥选项的不同方式的烹饪书。

来源:https ://pysftp.readthedocs.io/en/release_0.2.9/cookbook.html

默认情况下启用主机密钥检查。默认情况下它将使用 ~/.ssh/known_hosts 。如果您希望禁用主机密钥检查(不建议),您将需要修改默认 CnOpts 并将 .hostkeys 设置为 None。

import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
    # do stuff here
Run Code Online (Sandbox Code Playgroud)

要使用完全不同的known_hosts 文件,您可以通过在实例化时指定该文件来覆盖 CnOpts 查找 ~/.ssh/known_hosts。

import pysftp
cnopts = pysftp.CnOpts(knownhosts='path/to/your/knownhostsfile')

with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
    # do stuff here
Run Code Online (Sandbox Code Playgroud)

如果您希望使用 ~/.ssh/known_hosts 但添加其他已知主机密钥,您可以使用 .load 方法与更新其他known_host 格式文件合并。

import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('path/to/your/extra_knownhosts')
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
    # do stuff here
Run Code Online (Sandbox Code Playgroud)


wil*_*087 5

尝试使用pysftp库的0.2.8版本。 $ 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
Run Code Online (Sandbox Code Playgroud)

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

  • 你能详细说明一下吗?我浏览了该链接,但实际上没有找到任何适当的解释为什么降级会有所帮助。虽然你的陈述*“这里是所有细节”*表明应该有一些。 (2认同)

小智 5

如果您尝试通过 pysftp 连接到“普通”FTP,则必须将主机密钥设置为“无”。

import pysftp

cnopts = pysftp.CnOpts()
cnopts.hostkeys = None 
with pysftp.Connection(host='****',username='****',password='***',port=22,cnopts=cnopts) as sftp:
    print('DO SOMETHING')
Run Code Online (Sandbox Code Playgroud)