Python 使用 pysftp 验证主机密钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38939454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Verify host key with pysftp
提问by Gabriel Theodoulos
I am writing a program using pysftp, and it wants to verify the SSH host Key against C:\Users\JohnCalvin\.ssh\known_hosts
.
我正在使用 pysftp 编写一个程序,它想根据C:\Users\JohnCalvin\.ssh\known_hosts
.
Using PuTTY, the terminal program is saving it to the Registry [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys]
.
使用 PuTTY,终端程序将其保存到 Registry [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys]
。
How do I reconcile the difference between pysftp and PuTTY?
如何调和 pysftp 和 PuTTY 之间的差异?
My code is:
我的代码是:
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()
The Error Response I am receiving is:
我收到的错误响应是:
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 initself._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 delself.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'
E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py:61: UserWarning:
无法从 C:\Users\JohnCalvin.ssh\known_hosts 加载主机密钥。
您将需要显式加载 HostKeys (cnopts.hostkeys.load(filename)) 或禁用 HostKey 检查 (cnopts.hostkeys = None)。warnings.warn(wmsg, UserWarning) 回溯(最近一次调用):文件“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', username='root', password='********') 文件“E :\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py", line 132, in initself._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("找不到主机 %s 的主机密钥。”% 主机)paramiko.ssh_exception.SSHException:找不到主机 138.99.99.129 的主机密钥。异常被忽略: > 回溯(最近一次调用最后一次):文件“E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp__init__.py”,第 1013 行,在 delself.close() 文件“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'
回答by Noam Peled
One option is to disable the host key requirement:
一种选择是禁用主机密钥要求:
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
sftp.put(local_path, remote_path)
You can find more info about that here: https://stackoverflow.com/a/38355117/1060738
你可以在这里找到更多信息:https: //stackoverflow.com/a/38355117/1060738
Important note:
重要的提示:
By setting cnopts.hostkeys=None
you'll lose the protection against Man-in-the-middle attacks by doing so. Use @martin-prikryl answer to avoid that.
通过设置,cnopts.hostkeys=None
您将失去对中间人攻击的保护。使用 @martin-prikryl 答案来避免这种情况。
回答by Martin Prikryl
Do not set cnopts.hostkeys = None
(as the most upvoted answer shows), unless you do not care about security. You lose a protection against Man-in-the-middle attacksby doing so.
不要设置cnopts.hostkeys = None
(如最受好评的答案所示),除非您不关心安全性。这样做将失去对中间人攻击的保护。
Use CnOpts.hostkeys
(returns HostKeys
) to manage trusted host keys.
使用CnOpts.hostkeys
(returns HostKeys
) 来管理受信任的主机密钥。
cnopts = pysftp.CnOpts(knownhosts='known_hosts')
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
where the known_hosts
contains a server public key[s] in a format like:
其中known_hosts
包含服务器公钥[s],格式如下:
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
If you do not want to use an external file, you can also use
如果不想使用外部文件,也可以使用
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:
Though as of pysftp 0.2.9, this approach will issue a warning, what seems like a bug:
"Failed to load HostKeys" warning while connecting to SFTP server with pysftp
尽管从 pysftp 0.2.9 开始,这种方法会发出警告,这似乎是一个错误:
使用 pysftp 连接到 SFTP 服务器时出现“无法加载主机密钥”警告
An easy way to retrieve the host key in this format is using OpenSSH ssh-keyscan
:
以这种格式检索主机密钥的一种简单方法是使用 OpenSSH ssh-keyscan
:
$ ssh-keyscan example.com
# example.com SSH-2.0-OpenSSH_5.3
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
You can also make the application do the same automatically:
Use Paramiko AutoAddPolicy with pysftp
(It will automatically add host keys of new hosts to known_hosts
, but for known host keys, it will not accept a changed key)
您还可以让应用程序自动执行相同的操作:
将 Paramiko AutoAddPolicy 与 pysftp 一起使用
(它会自动将新主机的主机密钥添加到known_hosts
,但对于已知主机密钥,它不会接受更改的密钥)
Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.
虽然为了绝对安全,您不应该远程检索主机密钥,因为您无法确定,如果您还没有受到攻击。
See my article Where do I get SSH host key fingerprint to authorize the server?
It's for my WinSCP SFTP client, but most information there is valid in general.
请参阅我的文章从何处获取 SSH 主机密钥指纹以授权服务器?
它适用于我的 WinSCP SFTP 客户端,但那里的大多数信息通常都是有效的。
If you need to verify the host key using its fingerprint only, see Python - pysftp / paramiko - Verify host key using its fingerprint.
如果您只需要使用其指纹验证主机密钥,请参阅Python - pysftp / paramiko - 使用其指纹验证主机密钥。
回答by wilo087
Try to use the 0.2.8 version of pysftp library.
$ pip uninstall pysftp && pip install pysftp==0.2.8
尝试使用 0.2.8 版本的 pysftp 库。
$ pip uninstall pysftp && pip install pysftp==0.2.8
And try with this:
并尝试这样做:
try:
ftp = pysftp.Connection(host, username=user, password=password)
except:
print("Couldn't connect to ftp")
return False
Why this? Basically is a bug with the 0.2.9 of pysftp here all details https://github.com/Yenthe666/auto_backup/issues/47
为什么这个?基本上是pysftp 0.2.9的一个bug这里所有细节 https://github.com/Yenthe666/auto_backup/issues/47
回答by Pawe? Mi?osz
If You try to connect by pysftp to "normal" FTP You have to set hostkey to None.
如果您尝试通过 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')
回答by Yugendhar Anveshra
Cook book to use different ways of pysftp.CnOpts() and hostkeys options.
Cook book 使用不同方式的 pysftp.CnOpts() 和 hostkeys 选项。
Source : https://pysftp.readthedocs.io/en/release_0.2.9/cookbook.html
来源:https: //pysftp.readthedocs.io/en/release_0.2.9/cookbook.html
Host Key checking is enabled by default. It will use ~/.ssh/known_hosts by default. If you wish to disable host key checking (NOT ADVISED) you will need to modify the default CnOpts and set the .hostkeys to None.
默认情况下启用主机密钥检查。默认情况下,它将使用 ~/.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
To use a completely different known_hosts file, you can override CnOpts looking for ~/.ssh/known_hosts by specifying the file when instantiating.
要使用完全不同的 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
If you wish to use ~/.ssh/known_hosts but add additional known host keys you can merge with update additional known_host format files by using .load method.
如果您希望使用 ~/.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
回答by Fabian
I've implemented auto_add_key
in my pysftp github fork.
我已经auto_add_key
在我的pysftp github fork 中实现了。
auto_add_key
will add the key to known_hosts
if auto_add_key=True
Once a key is present for a host in known_hosts
this key will be checked.
auto_add_key
将把密钥添加到known_hosts
如果此密钥中auto_add_key=True
的主机存在known_hosts
密钥将被检查。
Please reffer Martin Prikryl-> answerabout security concerns.
请参考Martin Prikryl->关于安全问题的回答。
Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.
虽然为了绝对安全,您不应该远程检索主机密钥,因为您无法确定,如果您还没有受到攻击。
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()
Note: 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
回答by Hannes Rautenbach
Connect to the server first with a Windows ssh client that uses the known_hosts file. PuTTy stores the data in the windows registry,however OpenSSH uses the known_hosts file, and will add entries in there after you connect. Default location for the file is %USERPROFILE%.ssh. I hope this helps
首先使用使用 known_hosts 文件的 Windows ssh 客户端连接到服务器。PuTTy 将数据存储在 Windows 注册表中,但是 OpenSSH 使用 known_hosts 文件,并会在您连接后在其中添加条目。该文件的默认位置是 %USERPROFILE%.ssh。我希望这有帮助
回答by Omagano Uushona
Hi We sort of had the same problem if I understand you well. So check what pysftp version you're using. If it's the latest one which is 0.2.9 downgrade to 0.2.8. Check this out. https://github.com/Yenthe666/auto_backup/issues/47
嗨,如果我理解你的话,我们有同样的问题。因此,请检查您使用的 pysftp 版本。如果是最新的 0.2.9 降级到 0.2.8。看一下这个。https://github.com/Yenthe666/auto_backup/issues/47
回答by Andrew Garcia
FWIR, if authentication is only username & pw, add remote server ip address to known_hosts like ssh-keyscan -H 192.168.1.162 >> ~/.ssh/known_hosts
for ref https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your-knownhosts-file-in-linux/
FWIR,如果身份验证只是用户名和密码,请将远程服务器 IP 地址添加到 known_hosts 中,例如ssh-keyscan -H 192.168.1.162 >> ~/.ssh/known_hosts
参考https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your- knownhosts-file-in-linux/