Paramiko建立SSH连接时Hostkey报错的规避方案
问题根因
触发Hostkey_Error的核心原因是本地存储的远程SSH主机密钥,和连接时远程服务器实际返回的密钥不匹配:
- 你当前代码里配置的
paramiko.AutoAddPolicy()策略,仅在本地完全没有对应IP的主机密钥记录时,才会自动把远程返回的密钥写入本地known_hosts文件。 - 一旦远程服务器重装系统、SSH服务重新生成主机密钥、目标IP对应多台轮询的主机、或者本地known_hosts里残留了旧的错误密钥,
AutoAddPolicy()不会自动覆盖已有的旧密钥记录,就会直接抛出密钥校验失败的错误。 - 偶发的场景基本对应密钥临时变更、多节点轮询、known_hosts文件加载/写入权限异常这几类情况。
解决方案
根据你的环境安全要求二选一即可:
方案1:生产环境/公网连接(推荐)
不要跳过主机密钥校验,提前预存可信的目标主机公钥,从根源避免校验报错,同时不存在中间人攻击风险:
import paramiko import base64 from paramiko import Ed25519Key, ECDSAKey, RSAKey ssh = paramiko.SSHClient() # 可选:如果不需要加载系统默认的known_hosts避免旧密钥干扰,可以注释掉下一行 # ssh.load_system_host_keys() # 提前通过可信渠道获取目标主机的公钥,替换下面的密钥类型和公钥内容 # 公钥获取方式:在可信网络下执行 ssh-keyscan 你的目标IP,输出内容第二段是密钥类型,第三段是公钥字符串 host_key_type = "ssh-ed25519" host_key_str = "AAAAC3NzaC1lZDI1NTE5AAAAIxxxxxxxx替换为你拿到的实际公钥内容xxxxxxxx" if host_key_type == "ssh-ed25519": key = Ed25519Key(data=base64.b64decode(host_key_str)) elif host_key_type == "ssh-rsa": key = RSAKey(data=base64.b64decode(host_key_str)) elif host_key_type.startswith("ecdsa-sha2-"): key = ECDSAKey(data=base64.b64decode(host_key_str)) # 手动把可信密钥加入客户端密钥列表,优先级高于本地文件存储的密钥 ssh.get_host_keys().add(IP, host_key_type, key) ssh.set_missing_host_key_policy(paramiko.RejectPolicy()) ssh.connect(IP, username=USER, password=PSW, look_for_keys=False)
如果需要持久化存储密钥,也可以手动指定独立的known_hosts文件路径,避免系统默认文件的权限问题:
# 替换为你自己的可读写文件路径 ssh.load_host_keys("./custom_known_hosts")
方案2:内网测试/完全可控环境(不推荐公网使用)
如果是内网测试环境,不需要做严格的主机密钥校验,可以自定义密钥策略,遇到密钥不匹配时自动覆盖本地旧密钥,彻底消除这类报错:
import paramiko import os class AutoOverwriteHostKeyPolicy(paramiko.MissingHostKeyPolicy): def missing_host_key(self, client, hostname, key): # 直接用新返回的密钥覆盖本地旧记录 client._host_keys.add(hostname, key.get_name(), key) if client._host_keys_filename and os.access(client._host_keys_filename, os.W_OK): client.save_host_keys(client._host_keys_filename) ssh = paramiko.SSHClient() # 建议指定独立的known_hosts文件,避免修改系统默认的密钥记录 ssh.load_host_keys("./test_known_hosts") ssh.set_missing_host_key_policy(AutoOverwriteHostKeyPolicy()) ssh.connect(IP, username=USER, password=PSW, look_for_keys=False)
注意:这个方案会完全忽略主机密钥变更的校验逻辑,存在被中间人攻击的风险,绝对不要在公网生产环境使用。
内容的提问来源于stack exchange,提问作者Inuyasha84
相关产品推荐
相关产品推荐

