升级Ubuntu从18.04到22.04后,PHP脚本SSH指纹验证不匹配但终端SSH连接正常的问题咨询
升级Ubuntu从18.04到22.04后,PHP脚本SSH指纹验证不匹配但终端SSH连接正常的问题咨询
嗨,这个问题我之前帮朋友排查过类似的,核心原因大概率是PHP ssh2扩展在版本升级后,ssh2_fingerprint()函数的默认输出格式变了,而非远程服务器的公钥指纹真的变了,咱们一步步拆解来看:
问题根源分析
- 你之前在Ubuntu 18.04+PHP7.2环境下,搭配的是较旧版本的
php-ssh2扩展,依赖的libssh2库版本也偏低。当时调用ssh2_fingerprint($session, SSH2_FINGERPRINT_SHA1)返回的是带冒号分隔的十六进制字符串(比如aa:bb:cc:dd:ee:...),这和终端ssh命令默认显示的SHA1指纹格式完全一致。 - 升级到Ubuntu 22.04+PHP8.1后,
php-ssh2扩展依赖的libssh2库版本大幅更新,此时仅传入SSH2_FINGERPRINT_SHA1参数时,函数默认返回的是不带冒号的纯十六进制字符串(比如aabbccddee...)。这就导致你之前存储的旧指纹(带冒号)和新返回的指纹格式不匹配,触发了验证错误——但远程服务器的公钥其实根本没动,所以终端SSH连接的指纹显示完全正常。
解决方案(二选一即可)
调整PHP代码,统一指纹格式
如果你想保留之前存储的指纹格式,只需要在调用ssh2_fingerprint()时额外传入SSH2_FINGERPRINT_HEX参数,强制返回带冒号的格式:$fingerprint = ssh2_fingerprint($session, SSH2_FINGERPRINT_SHA1 | SSH2_FINGERPRINT_HEX);这样就能直接和你之前存储的指纹匹配,不需要修改任何存储值。
转换现有存储的指纹格式
如果你不想改动代码,可以把存储的旧指纹去掉所有冒号,转换成纯十六进制字符串。比如把aa:bb:cc:dd改成aabbccdd,就能和新函数返回的格式对齐。
快速验证方法
你可以临时在脚本里打印当前返回的指纹,再和终端获取的指纹对比确认:
- 终端获取不带冒号的SHA1指纹:
ssh-keygen -lf <(ssh-keyscan 你的远程主机地址 2>/dev/null) | grep SHA1 | awk '{print $2}' | sed 's/SHA1://' - 终端获取带冒号的SHA1指纹:
把这些结果和PHP脚本输出的指纹对比,就能直观看到格式差异啦。ssh-keygen -lf <(ssh-keyscan 你的远程主机地址 2>/dev/null) | grep SHA1 | awk '{print $2}' | sed 's/SHA1://' | sed 's/../&:/g' | sed 's/:$//'
备注:内容来源于stack exchange,提问作者cazort
相关产品推荐
相关产品推荐

