YII2框架调用file_get_contents报OpenSSL 0A000126错误如何解决
问题背景
问题截图
基于PHP搭配YII2框架搭建的站点,调用file_get_contents($requestUrl, false, stream_context_create($arrContextOptions))发起请求时抛出报错:
error:0A000126:SSL routines::unexpected eof while reading
此前尝试编辑openssl.cnf文件启用legacy provider修复,未生效。
当前服务器环境:
- Web服务:Nginx 1.18.0
- 操作系统:Ubuntu 22.04 LTS
- PHP版本:7.4.29
- OpenSSL版本:1.1.1d
解决思路
按优先级从高到低尝试,优先选择改造成本低的代码层方案:
- 调整SSL请求上下文参数,直接修改
$arrContextOptions配置,兼容异常握手场景:
$arrContextOptions = [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true, 'ciphers' => 'DEFAULT:!SSLv3', 'disable_compression' => true, ], 'http' => [ 'timeout' => 15, 'protocol_version' => 1.1, 'header' => "Connection: close\r\n" ] ];
该报错核心原因是OpenSSL在SSL握手阶段未收到对端完整的连接关闭通知就被断连,强制指定HTTP 1.1协议、添加Connection: close头可规避长连接复用导致的流量截断,无需修改系统配置。
- 修正OpenSSL配置加载路径,之前修改openssl.cnf未生效通常是改了错误的配置文件。先执行命令
php -i | grep -i openssl.conf查看PHP进程实际读取的OpenSSL配置文件路径,不要直接修改系统全局的/etc/ssl/openssl.cnf。在对应配置文件顶部添加以下配置:
openssl_conf = default_conf [default_conf] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.2 CipherString = DEFAULT:@SECLEVEL=1
修改完成后执行systemctl restart php7.4-fpm重启PHP进程,仅重启Nginx不会加载新的OpenSSL配置。
- 替换请求实现方式,放弃file_get_contents发外部请求,改用CURL扩展或者YII2自带的HTTP客户端组件发请求,CURL的SSL握手逻辑和PHP原生stream流相互独立,可直接规避大部分stream层的SSL异常,示例代码:
$ch = curl_init($requestUrl); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, ]); $response = curl_exec($ch); $curlErr = curl_error($ch); curl_close($ch);
- 排查网络链路拦截,在服务器命令行执行
curl -v 目标请求URL,观察SSL握手过程输出,如果在Server Hello阶段直接断开,说明是服务器出站防火墙、云安全组或WAF中途截断了SSL流量,需要对应放通规则。
内容的提问来源于stack exchange,提问作者Salik Mohammad
相关产品推荐
相关产品推荐

