如何解决Paramiko中的BadHostKeyException异常?
解决Paramiko BadHostKeyException异常问题
问题描述
你编写了如下代码连接Linux主机执行命令,即使添加了WarningPolicy和AutoAddPolicy,仍遇到BadHostKeyException异常:
print("---CCCCCCCCCCCCC---",commands) client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.WarningPolicy) client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(ipAddress, port=22, username=sshUser, password=sshPassword) self.logger.info("executeOnRemoteShell - Created SSH connection to " + ipAddress) stdin, stdout, stderr = client.exec_command(commands) result = str(stdout.readlines()[0].rstrip())
完整错误信息:
paramiko.ssh_exception.BadHostKeyException: Host key for server '45.32.23.23' does not match: got 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGcWA6JnHBbVIGsdC+USD2GOxWNy+R8hiiFiLse75rs1JRTWN8i3ol3yZ4OhFhQl4upZ7f5/scFzw4DqoMrhRIE=', expected 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJSELS2mT8SED8I7QFf5YkkvD5n4LCHUkX4ykeemwuqGHOBVHixQMBtKWF9lFuKFhKOCNsifRPK1FfkT23glapI
原因分析
client.load_system_host_keys()会加载本地~/.ssh/known_hosts文件中的记录,目标IP的旧密钥已存在,但和当前服务器返回的密钥不匹配。AutoAddPolicy只处理首次连接、本地无该主机密钥记录的场景,无法解决已有密钥不匹配的问题。- 你连续两次调用
set_missing_host_key_policy,后一次的AutoAddPolicy()会覆盖前一次的WarningPolicy,导致前者完全无效。
解决方法
方法一:手动更新本地密钥记录(推荐,安全)
找到本地的~/.ssh/known_hosts文件,删除包含45.32.23.23的那一行,重新运行代码后,AutoAddPolicy会自动将新主机密钥添加到文件中。
方法二:代码自动处理密钥冲突(适合自动化场景)
如果需要代码自动处理旧密钥冲突,可以先移除本地存储的旧密钥再重试连接:
print("---CCCCCCCCCCCCC---", commands) client = paramiko.SSHClient() # 加载系统主机密钥(不需要可注释) client.load_system_host_keys() # 仅设置一次缺失密钥策略 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(ipAddress, port=22, username=sshUser, password=sshPassword) except paramiko.BadHostKeyException: # 移除本地存储的目标IP旧密钥 host_keys = client.get_host_keys() if ipAddress in host_keys: del host_keys[ipAddress] host_keys.save(client._system_host_keys_path) # 重试连接 client.connect(ipAddress, port=22, username=sshUser, password=sshPassword) self.logger.info("executeOnRemoteShell - Created SSH connection to " + ipAddress) stdin, stdout, stderr = client.exec_command(commands) result = str(stdout.readlines()[0].rstrip())
方法三:跳过密钥验证(仅测试环境用,不安全)
测试环境下可临时跳过主机密钥验证,但生产环境绝对禁止使用:
print("---CCCCCCCCCCCCC---", commands) client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接时禁用主机密钥检查(风险极高) client.connect(ipAddress, port=22, username=sshUser, password=sshPassword, hostkey=None) self.logger.info("executeOnRemoteShell - Created SSH connection to " + ipAddress) stdin, stdout, stderr = client.exec_command(commands) result = str(stdout.readlines()[0].rstrip())
内容的提问来源于stack exchange,提问作者mac
相关产品推荐
相关产品推荐

