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

Posted

技术标签:

【中文标题】使用 pysftp 针对使用自定义端口的 known_hosts 文件验证主机密钥【英文标题】:Verify host key with pysftp against known_hosts file with custom port 【发布时间】:2021-10-12 13:10:46 【问题描述】:

我正在尝试使用 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()

注意:

    服务器使用非标准端口 服务器仅使用列出的五个密码来协商连接,因此此选项是强制性的

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

SSHException: 找不到主机 data-nz.metservice.com 的主机密钥。

我已经阅读了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 确认。知道我的程序有什么问题吗?

【问题讨论】:

【参考方案1】:

我猜问题是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 将能够找到它。

【讨论】:

以上是关于使用 pysftp 针对使用自定义端口的 known_hosts 文件验证主机密钥的主要内容,如果未能解决你的问题,请参考以下文章

使用Prometheus针对自己的服务器采集自定义的参数

使用 pysftp 验证主机密钥

使用 pysftp 验证主机密钥

使用 pysftp 验证主机密钥

使用pysftp通过跳转服务器连接

添加自定义监控项目邮件告警