PHP file_get_contents请求HTTPS报0A000126 SSL意外EOF错误
问题根因
- 报错
error:0A000126:SSL routines::unexpected eof while reading是OpenSSL 3.0.2、3.0.3版本的已知兼容性bug,和证书校验逻辑无关,这也是你关闭verify_peer、verify_peer_name后依然报错的核心原因。 - 触发逻辑:部分API服务端在SSL握手结束时,没有严格遵循TLS协议规范发送
close_notify告警就直接断开连接,OpenSSL 3.0早期版本将这种非标准实现判定为致命错误,而浏览器、OpenSSL 1.x系列版本都会默认兼容该行为,所以会出现浏览器能访问、PHP环境报错的差异。 - 从你贴的环境检测结果可以直接对应:当前使用的OpenSSL库版本正好是存在该bug的3.0.3版本。配置项中
openssl.cafile、openssl.capath为空属于CA证书路径配置缺失,是独立的安全配置问题,不是触发本次报错的直接原因。
修复方案
按照优先级从高到低选择:
1. 升级OpenSSL版本(根治方案)
OpenSSL官方在3.0.4版本中已经修复了该问题,将未收到close_notify就断开连接的行为从致命错误调整为可兼容的警告,直接升级系统OpenSSL包到3.0.4及以上稳定版本,重启PHP CLI/FPM进程即可恢复正常,不需要修改业务代码。
升级完成后记得补全CA证书配置:
- 找到系统CA证书存储路径,主流发行版默认路径为
/etc/pki/tls/certs/ca-bundle.crt(CentOS/RHEL系)或/etc/ssl/certs/ca-certificates.crt(Debian/Ubuntu系) - 编辑php.ini配置文件,将
openssl.cafile的值设置为上述CA证书路径,保存后重启PHP进程 - 删除代码中关闭SSL证书校验的相关配置,避免引入中间人攻击风险
2. 调整SSL上下文配置(无需改动环境,快速生效)
如果暂时无法升级服务器OpenSSL版本,可以在原有stream上下文配置中补充参数,绕过该bug:
$arrContextOptions=array( "ssl"=>array( "verify_peer"=>false, // 配置完CA证书后请删除这两行,开启校验 "verify_peer_name"=>false, "disable_compression" => true, "crypto_method" => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT, ), ); $geoData = file_get_contents($requestUrl, false, stream_context_create($arrContextOptions));
3. 改用curl扩展发起请求
同版本OpenSSL环境下,curl扩展默认兼容服务端未发送close_notify的非标准行为,可以直接替换file_get_contents实现请求:
$ch = curl_init($requestUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 配置完CA证书路径后请开启以下两项校验 // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $geoData = curl_exec($ch); curl_close($ch);
注意:永久关闭SSL证书校验会导致HTTPS请求失去防中间人攻击的能力,仅可作为临时调试手段使用,生产环境必须开启证书校验并正确配置CA证书路径。
内容的提问来源于stack exchange,提问作者Kos-Mos
相关产品推荐
相关产品推荐

