我正在使用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'
答案 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()
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/