使用 pysftp 针对具有自定义端口的 known_hosts 文件验证主机密钥

Verify host key with pysftp against known_hosts file with custom port

我正在尝试使用 pysftp 登录 SFTP 服务器。

这是我正在测试的代码:

import pysftp
cnopts = pysftp.CnOpts()
# cnopts.hostkeys = None
host = 'data-nz.metservice.com'
username = 'my_user'
password = 'my_passwd'
ciphers = ['aes128-cbc', '3des-cbc', 'blowfish-cbc', 'aes192-cbc', 'aes256-cbc']
  
with pysftp.Connection(host, username=username, password=password,
                       port=9022, ciphers=ciphers, cnopts=cnopts) as sftp:
  
    sftp.listdir()

注意:

  1. 服务器使用非标准端口
  2. 服务器仅使用列出的五个密码来协商连接,因此此选项是必需的

此代码失败,因为找不到主机密钥:

SSHException: No hostkey for host data-nz.metservice.com found.

我已阅读 this question,并且我已成功使用设置 cnopts.hostkeys=None 的解决方法(请参阅我的代码中注释掉的行)。但显然我想消除这个安全漏洞。但是我不知道如何处理这个异常。我已使用纯 sftp 登录,以确保将所需的行添加到我的 known_hosts。这个动作实际上添加了两行(我不完全清楚其内容,因为没有明确引用 URL,但无论如何......),现在 sftp 没有抱怨:

|1|l+HfDGPUhea+8cUzCS+jq2HGcBg=|XMWhbkgujRtW1lJ4E93sTidUiCs= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8N65MCdnbHjaEDxkZPPq1QO0RLwP3cdm9Gb9BAMS0mFH39d7/yHIerA6yFZRW27u3NClI7V1F3hDuheoCUomeF9Q9ioaeQ2dlX27hmGf611RpSfI/vGgnmipHYzzHsCIJi0LxuowCouKNw8g1v1e2VzsVWFPaq+cDeuUpDwpBKWnxQUWN7U9mzN1k0sDALimWOzhfQmXtCzPkHqERUcPpdU7/zWP8Xk9H7FQxgiPFa+EC5xuCzn01CcJppQ8VBqL9R6SNNP/d9ymQWh3cotXe6sj5gt2MdfbAUfxddQITW1rU+LSOkG21QPMq0VBDJwWf9RpqhnqcvusZIFVGyOsn
|1|uILdQCq4UAlxnruPlWnb7vwpWbc=|AOjbzHHXJ44ibhLVJJSGk++ep+U= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8N65MCdnbHjaEDxkZPPq1QO0RLwP3cdm9Gb9BAMS0mFH39d7/yHIerA6yFZRW27u3NClI7V1F3hDuheoCUomeF9Q9ioaeQ2dlX27hmGf611RpSfI/vGgnmipHYzzHsCIJi0LxuowCouKNw8g1v1e2VzsVWFPaq+cDeuUpDwpBKWnxQUWN7U9mzN1k0sDALimWOzhfQmXtCzPkHqERUcPpdU7/zWP8Xk9H7FQxgiPFa+EC5xuCzn01CcJppQ8VBqL9R6SNNP/d9ymQWh3cotXe6sj5gt2MdfbAUfxddQITW1rU+LSOkG21QPMq0VBDJwWf9RpqhnqcvusZIFVGyOsn

但是 Python 似乎仍然没有确认主机密钥。知道我的程序有什么问题吗?

我猜问题是 pysftp 在 known_hosts 文件中查找主机密钥时不支持自定义端口。

添加这样的条目:

data-nz.metservice.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8N65MCdnbHjaEDxkZPPq1QO0RLwP3cdm9Gb9BAMS0mFH39d7/yHIerA6yFZRW27u3NClI7V1F3hDuheoCUomeF9Q9ioaeQ2dlX27hmGf611RpSfI/vGgnmipHYzzHsCIJi0LxuowCouKNw8g1v1e2VzsVWFPaq+cDeuUpDwpBKWnxQUWN7U9mzN1k0sDALimWOzhfQmXtCzPkHqERUcPpdU7/zWP8Xk9H7FQxgiPFa+EC5xuCzn01CcJppQ8VBqL9R6SNNP/d9ymQWh3cotXe6sj5gt2MdfbAUfxddQITW1rU+LSOkG21QPMq0VBDJwWf9RpqhnqcvusZIFVGyOsn

或者直接使用 Paramiko(pysftp 是 Paramiko 的包装器),因为 Paramiko 正确实现了自定义端口的主机密钥查找。


一些背景:原始 known_hosts 开头的代码是哈希 host[:port] 标识符。 Pysftp 在查找条目时没有使用端口,因此找不到正确的端口。如果您在没有自定义端口的情况下添加伪造(散列或未散列)条目,pysftp 将能够找到它。