Ansible中OpenSSH连接失败但Paramiko可用的原因与排查
Ansible OpenSSH连接失效但Paramiko可用的问题排查与修复
问题描述
执行以下Ansible Playbook命令时:
ansible-playbook -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml -c ssh
出现连接失败错误:
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ", "unreachable": true}
但添加-c paramiko参数指定Paramiko连接后,命令可正常运行:
ansible-playbook -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml -c paramiko
已知环境信息
- 本地主机:Ubuntu 20.04
- 远程主机:CentOS 7
- Ansible版本:core 2.13.6
Verbose模式输出
启用-vvv参数执行命令:
ansible-playbook -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml -c ssh -vvv
输出内容:
/usr/lib/python3/dist-packages/paramiko/transport.py:236: CryptographyDeprecationWarning: Blowfish has been deprecated "class": algorithms.Blowfish, ansible-playbook [core 2.13.6] config file = /etc/ansible/ansible.cfg configured module search path = ['/home/john/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /home/john/.local/lib/python3.10/site-packages/ansible ansible collection location = /home/john/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible-playbook python version = 3.10.6 (main, Nov 2 2022, 18:53:38) [GCC 11.3.0] jinja version = 3.1.2 libyaml = True Using /etc/ansible/ansible.cfg as config file host_list declined parsing /home/john/test/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory as it did not pass its verify_file() method script declined parsing /home/john/test/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory as it did not pass its verify_file() method auto declined parsing /home/john/test/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory as it did not pass its verify_file() method Parsed /home/john/test/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory inventory source with ini plugin Skipping callback 'default', as we already have a stdout callback. Skipping callback 'minimal', as we already have a stdout callback. Skipping callback 'oneline', as we already have a stdout callback. PLAYBOOK: playbook.yml ************************************************************************************************* 1 plays in playbook.yml PLAY [all] ************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************* task path: /home/john/test/playbook.yml:2 <127.0.0.1> ESTABLISH SSH CONNECTION FOR USER: vagrant <127.0.0.1> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o Port=2222 -o 'IdentityFile="/home/john/test/.vagrant/machines/default/virtualbox/private_key"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="vagrant"' -o ConnectTimeout=10 -o 'ControlPath="/home/john/.ansible/cp/055b8f4af0"' 127.0.0.1 '/bin/sh -c '"'"'echo ~vagrant && sleep 0'"'"'' <127.0.0.1> (255, b'/home/vagrant\n', b'') fatal: [default]: UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: ", "unreachable": true } PLAY RECAP ************************************************************************************************************* default : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
一、OpenSSH连接失效但Paramiko可用的常见原因
- SSH版本兼容性:Ubuntu 20.04自带的OpenSSH客户端版本较新,CentOS 7的OpenSSH服务端版本偏旧,新客户端默认的加密算法、密钥交换方式不被旧服务端支持。
- Ansible SSH插件参数冲突:从verbose输出可见,Ansible默认启用了
ControlMaster=auto连接复用功能,可能因权限、路径问题导致连接失败;或者PreferredAuthentications认证顺序存在隐藏兼容性问题。 - 密钥权限问题:OpenSSH对私钥文件权限要求严格(必须为
600),Paramiko对权限的容忍度更高,若密钥权限不符合要求会导致OpenSSH连接失败。 - 端口转发逻辑差异:Vagrant将远程22端口映射到本地2222,OpenSSH与Paramiko处理端口转发的逻辑不同,可能存在超时、连接复用的冲突。
二、调试OpenSSH连接的具体步骤
手动执行OpenSSH命令测试
复制Ansible生成的SSH命令,去掉Control相关参数后手动执行,查看详细错误:ssh -C -o Port=2222 -o 'IdentityFile="/home/john/test/.vagrant/machines/default/virtualbox/private_key"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="vagrant"' -o ConnectTimeout=10 127.0.0.1 '/bin/sh -c "echo ~vagrant && sleep 0"'检查密钥文件权限
修正私钥权限至OpenSSH要求的600:chmod 600 /home/john/test/.vagrant/machines/default/virtualbox/private_key关闭连接复用功能测试
在Ansible命令中添加参数禁用ControlMaster:ansible-playbook -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml -c ssh -o ControlMaster=no指定兼容的加密算法
如果手动连接提示算法不兼容,指定CentOS 7支持的算法:ansible-playbook -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml -c ssh -o KexAlgorithms=diffie-hellman-group-exchange-sha256 -o Ciphers=aes256-ctr
三、修复OpenSSH连接的方案
修改Ansible全局配置
在/etc/ansible/ansible.cfg或~/.ansible.cfg中添加以下配置,适配旧服务端:[ssh_connection] ssh_args = -o ControlMaster=no -o KexAlgorithms=diffie-hellman-group-exchange-sha256 -o Ciphers=aes256-ctr升级远程主机OpenSSH服务
在CentOS 7上升级OpenSSH服务端(注意备份配置):sudo yum install -y openssh-server openssh-clients sudo systemctl restart sshd自动修正Vagrant生成的密钥权限
在Vagrantfile中添加钩子,每次启动虚拟机后自动修正私钥权限:config.vm.provision "shell", inline: <<-SHELL chmod 600 /home/vagrant/.ssh/authorized_keys SHELL config.trigger.after :up do run "chmod 600 .vagrant/machines/default/virtualbox/private_key" end
内容的提问来源于stack exchange,提问作者hangindev.com
相关产品推荐
相关产品推荐

