PHP SSH2扩展连接OpenSSH8.9失败,求安全兼容解决方案
环境信息
- Host_A:Ubuntu 18.04.6 LTS,PHP v7.2,OpenSSH v7.6
- Host_B:Ubuntu 22.04.5 LTS,OpenSSH v8.9
问题现象
从Host_A通过PHP SSH2扩展连接Host_B时,连接始终失败,PHP报错:
ssh2_connect(): Error starting up SSH connection(-5): Unable to exchange encryption keys
ssh2_connect(): Unable to connect to [Host_B]
Host_B的SSH日志显示:
sshd[###]: Unable to negotiate with [Host_A] port 55466: no matching host key type found. Their offer: ssh-rsa,ssh-dss [preauth]
注:无论使用ssh2_auth_password密码认证还是ssh2_auth_pubkey_file公钥文件认证,都会出现上述错误(错误发生在ssh2_connect阶段,早于认证步骤)。
原因分析
Host_B的OpenSSH 8.8+版本默认禁用了ssh-rsa和ssh-dss这两种存在安全风险的主机密钥算法,而当前使用的PHP SSH2扩展默认仅支持这两种算法,导致双方无共同支持的密钥算法,连接协商失败。
尝试指定现代算法ssh-ed25519时,执行ssh2_connect('Host_B', [Port], ['hostkey' => 'ssh-ed25519'])出现错误:
ssh2_connect(): Failed overriding HOSTKEY method
可选解决方案
方案1:升级PHP SSH2扩展及底层libssh2库
当前PHP SSH2扩展依赖的libssh2版本可能过低,不支持现代密钥算法的配置。操作步骤:
- 升级Host_A上的libssh2库到支持
ssh-ed25519的最新版本 - 重新编译安装PHP SSH2扩展,确保编译时调用新的libssh2库
- 再次尝试指定
hostkey参数为ssh-ed25519建立连接
方案2:改用其他SSH客户端库
放弃PHP SSH2扩展,选择支持现代SSH算法的替代方案:
- 使用
phpseclib纯PHP实现的SSH库,它原生支持ssh-ed25519等现代算法,无需依赖系统libssh2库 - 调用系统
ssh命令:通过PHP的exec()、shell_exec()等函数直接执行系统ssh命令连接Host_B并执行操作(需提前配置Host_A到Host_B的免密登录,确保操作安全性)
方案3:临时调整Host_B的SSH配置(不推荐)
如果无法升级Host_A的环境,可临时在Host_B的/etc/ssh/sshd_config中添加允许ssh-rsa的配置(仅作为过渡方案,存在安全风险):
HostKeyAlgorithms +ssh-rsa PubkeyAcceptedKeyTypes +ssh-rsa
修改后重启sshd服务:systemctl restart sshd
安全性说明
ssh-rsa和ssh-dss被OpenSSH弃用是因为存在明确的安全漏洞,不建议长期启用。优先选择方案1或方案2解决问题,避免引入安全隐患。
内容的提问来源于stack exchange,提问作者Alpaca

