Ansible 2.9 版本连接远程主机报错 SSH handshake failed 怎么解决

文章导读
Ansible 2.9 连接远程主机报 SSH handshake failed 通常是因为控制节点与目标主机的 SSH 加密算法不兼容,或者主机密钥验证被阻止。最推荐的处理方向是调整 ansible.cfg 中的 SSH 连接参数,长期建议升级 Ansible 核心版本。
📋 目录
  1. A 命令速用版
  2. B 为什么会这样
  3. C 分步处理
  4. D 怎么验证是否生效
  5. E 常见坑
  6. F 常见问题
A A

Ansible 2.9 连接远程主机报 SSH handshake failed 通常是因为控制节点与目标主机的 SSH 加密算法不兼容,或者主机密钥验证被阻止。最推荐的处理方向是调整 ansible.cfg 中的 SSH 连接参数,长期建议升级 Ansible 核心版本。

先说结论:该报错本质是 SSH 协议协商失败,多见于旧版 Ansible 客户端连接开启了严格安全策略的新版 Linux 主机。

  • 先确认:手动 SSH 登录目标主机是否成功,排除网络与基础服务问题。
  • 先处理:修改 ansible.cfg 中的 ssh_args 或关闭 host_key_checking 临时验证。
  • 再验证:使用 ansible ping 模块测试连接是否恢复。

命令速用版

若需快速验证是否为密钥检查导致,可在命令中临时关闭主机密钥检查,仅用于测试环境。

ansible all -m ping -u username -k `--extra-vars` "ansible_ssh_common_args='-o StrictHostKeyChecking=no'"

若需永久生效,编辑 ansible.cfg 文件,在 [defaults] 下添加或修改以下配置。

[defaults]
host_key_checking = False
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

为什么会这样

SSH handshake failed 核心原因是客户端与服务端在密钥交换算法或主机密钥类型上无法达成一致。Ansible 2.9 发布较早,默认使用的 SSH 算法可能被新版 OpenSSH 服务端禁用。例如 OpenSSH 8.8 版本之后默认禁用了 ssh-rsa 公钥算法,而旧版 Ansible 控制节点可能仍尝试使用该算法进行握手。此外,目标主机的 SSH 服务配置若限制了特定的 KexAlgorithms 或 HostKeyAlgorithms,也会直接导致握手阶段中断。

分步处理

按以下顺序排查,每一步完成后需确认是否解决,避免过度放宽安全策略。

步骤 1:手动验证 SSH 连通性
在控制节点使用 ssh 命令直接连接目标主机,观察报错信息。

ssh -v username@target_host

如果手动 SSH 也报错,问题在于系统 SSH 配置而非 Ansible 本身。如果手动 SSH 成功但 Ansible 失败,问题在于 Ansible 的 SSH 参数传递。

步骤 2:检查 Ansible 连接插件
Ansible 2.9 默认使用 smart 连接插件,可能调用 paramiko 或 ssh 命令。确认 ansible.cfg 中是否强制指定了连接方式。

ansible-config dump | grep CONNECTION

建议确保使用 ssh 连接插件,paramiko 在旧版本中对新算法支持较差。

Ansible 2.9 版本连接远程主机报错 SSH handshake failed 怎么解决

步骤 3:调整 SSH 算法配置
如果确认是算法不匹配,在 ansible.cfg 的 [defaults] 部分添加 ssh_args,允许特定算法。

[defaults]
ssh_args = -o KexAlgorithms=+diffie-hellman-group-exchange-sha256 -o HostKeyAlgorithms=+ssh-rsa

注意:添加算法前需确认目标主机支持该算法,否则无效。

步骤 4:升级 Ansible 版本
Ansible 2.9 已停止维护,长期解决方案是升级 Ansible Core 至受支持版本,以原生支持新 SSH 标准。

怎么验证是否生效

执行以下命令检查连接状态,返回 SUCCESS 表示修复成功。

ansible all -m ping -v

观察输出日志,确认不再出现 SSH handshake failed 或 Connection refused 错误。若使用 -v 参数,可查看详细的 SSH 握手过程,确认算法协商阶段通过。检查日志位置通常在 /var/log/secure 或 journald 中,确认服务端没有拒绝连接的记录。

常见坑

1. 生产环境关闭密钥检查:host_key_checking = False 会中间人攻击风险,仅建议在测试环境临时使用,生产环境应通过 known_hosts 管理密钥。
2. Python 版本不兼容:Ansible 2.9 对 Python 3 的支持有限,若目标主机仅安装 Python 3 且版本过高,可能导致连接模块执行失败,表现为连接报错。
3. 防火墙拦截:有时 handshake failed 是防火墙重置连接的误报,需确认目标主机 22 端口对控制节点 IP 开放。
4. 权限问题:确保控制节点的 SSH 私钥权限为 600,权限过宽会导致 SSH 客户端拒绝使用密钥。

常见问题

为什么手动 SSH 能成功但 Ansible 报错?

Ansible 可能使用了不同的 SSH 参数或连接插件。Ansible 默认会添加 ControlPersist 等参数,这些参数可能与特定 SSH 配置冲突,需检查 ansible.cfg 中的 ssh_args 设置。

升级 Ansible 会影响现有 playbook 吗?

大部分 playbook 兼容,但需测试 deprecated 模块。Ansible 2.9 到更高版本存在模块废弃情况,建议先在测试环境运行 ansible-playbook `--check` 验证。

如何永久修复算法不匹配问题?

最稳妥的方法是升级控制节点的 Ansible 版本和 SSH 客户端。若无法升级,需在 ansible.cfg 中明确指定服务端支持的 KexAlgorithms 和 HostKeyAlgorithms 列表。