关于python:使用pysftp验证主机密钥

Verify host key with pysftp

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

使用putty,终端程序将其保存到注册表[HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys]

如何协调Pysftp和Putty之间的差异?

我的代码是:

1
2
3
4
5
6
7
8
9
10
11
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:
Failed to load HostKeys from C:\Users\JohnCalvin.ssh\known_hosts.
You will need to explicitly load HostKeys
(cnopts.hostkeys.load(filename)) or disableHostKey checking
(cnopts.hostkeys = None). warnings.warn(wmsg, UserWarning) Traceback
(most recent call last): File
"E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 14, in

push_file_to_server() File"E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 7, in
push_file_to_server
s = sftp.Connection(host='138.99.99.129', username='root', password='********') File"E:\Program Files
(x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 132, in
init
self._tconnect['hostkey'] = self._cnopts.get_hostkey(host) File"E:\Program Files
(x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 71, in
get_hostkey
raise SSHException("No hostkey for host %s found." % host) paramiko.ssh_exception.SSHException: No hostkey for host 138.99.99.129
found. Exception ignored in: > Traceback (most
recent call last): File"E:\Program Files
(x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 1013, in
del
self.close() File"E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 784, in
close
if self._sftp_live: AttributeError: 'Connection' object has no attribute '_sftp_live'


以下解决方案对我有效:

1
2
3
4
5
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/3835517/1060738


不要设置cnopts.hostkeys = None(正如最乐观的答案所示),除非你不关心安全。你这样做会失去对中间人攻击的保护。

使用CnOpts.hostkeys(返回HostKeys)管理受信任的主机密钥。

1
2
3
4
cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('known_hosts')

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

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

1
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...

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

1
2
3
4
5
6
7
8
9
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

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

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

尽管为了绝对安全,您不应该远程检索主机密钥,因为如果您没有受到攻击,您不能确定。

请参阅我的文章,在哪里可以获得ssh主机密钥指纹来授权服务器?它是为我的winscp sftp客户机准备的,但是那里的大多数信息通常都是有效的。

如果只需要使用其指纹来验证主机密钥,请参见python-pysftp/paramiko-verify host key using its fingerprint。


尝试使用pysftp库的0.2.8版本。埃多克斯1〔6〕

尝试一下:

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

为什么?基本上是一个pysftp的0.2.9的bug这里是所有的细节https://github.com/yethe666/auto_备份/issues/47


嗨,如果我理解你的话,我们也有同样的问题。所以请检查您使用的Pysftp版本。如果是最新的0.2.9,则降级至0.2.8。看看这个。https://github.com/yethe666/auto_备份/issues/47


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