使用pysftp

时间:2016-08-14 05:30:27

标签: python ssh pysftp

我正在使用pysftp编写程序,并希望针对C:\Users\JohnCalvin\.ssh\known_hosts验证SSH主机密钥。

使用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()

我收到的错误回复是:

  

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 =无)。 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行,in   push_file_to_server       s = sftp.Connection(host =' 138.99.99.129',username =' root',password =' ********')文件" E:\ Program Files   (x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __。py",第132行,in   的初始化       self._tconnect [' hostkey'] = self._cnopts.get_hostkey(host)文件" E:\ Program Files   (x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __。py",第71行,in   get_hostkey       提升SSHException("找不到主机%s的主机键。"%host)paramiko.ssh_exception.SSHException:没有主机的主机密钥138.99.99.129   找到。在以下情况中忽略了例外:>追溯(大多数   最近的呼叫最后):文件" E:\ Program Files   (x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __。py",1013行,in   的德尔       self.close()文件" E:\ Program Files(x86)\ Anaconda3 \ lib \ site-packages \ pysftp__init __。py",line 784,in   关       if self._sftp_live:AttributeError:' Connection'对象没有属性' _sftp_live'

9 个答案:

答案 0 :(得分:51)

以下解决方案对我有用:

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

答案 1 :(得分:25)

请勿设置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 :(得分: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')

答案 3 :(得分:3)

使用不同的pysftp.CnOpts()和hostkeys选项来烹饪书籍。

来源: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

要使用完全不同的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

如果您希望使用〜/ .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

答案 4 :(得分:2)

尝试使用pysftp库的0.2.8版本。 some_column=map()

并尝试以下操作:


$ pip uninstall pysftp && pip install pysftp==0.2.8

为什么呢? 基本上是pysftp 0.2.9的错误 这里所有细节 heapq

答案 5 :(得分:1)

嗨,如果我理解你,我们会遇到同样的问题。因此,请检查您正在使用的pysftp版本。如果它是最新的0.2.9降级到0.2.8。 看一下这个。 https://github.com/Yenthe666/auto_backup/issues/47

答案 6 :(得分:0)

我在pysftp github fork中实现了auto_add_key

auto_add_key将把密钥添加到known_hosts,如果auto_add_key=True
known_hosts中为主机提供密钥后,将对其进行检查。

请参考Martin Prikryl-> answer关于安全方面的问题。

  

尽管出于绝对的安全性考虑,但是如果您尚未受到攻击,则不能确保无法远程获取主机密钥。

import pysftp as sftp

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

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

push_file_to_server()

注意:Why using context manager

import pysftp
with pysftp.Connection(host, username="whatever", password="whatever", auto_add_key=True) as sftp:
    #do your stuff here
#connection closed

答案 7 :(得分:-1)

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

答案 8 :(得分:-1)

FWIR,如果身份验证仅是用户名和密码,则将远程服务器ip地址添加到ssh-keyscan -H 192.168.1.162 >> ~/.ssh/known_hosts之类的known_hosts,以供参考https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your-knownhosts-file-in-linux/