本质是openssl与目标服务器tls协商失败,需修复证书链、校准时间、升级openssl≥1.1.1、显式指定tlsv1.2、排查cdn/waf干扰,禁用curlopt_ssl_verifypeer=false等不安全绕过。

在 Laravel 10 中使用 cURL 发起 HTTPS 请求时遇到 SSL 握手失败(如报错 curl: (35) SSL connect error 或 PHP 层抛出 CURLOPT_SSL_VERIFYPEER failed),本质是底层 OpenSSL 与目标服务器在 TLS 协商阶段无法达成一致。这不是 Laravel 框架本身的问题,而是 PHP cURL 扩展调用 OpenSSL 过程中触发的系统级验证失败。解决关键在于:**不绕过安全,而让验证链完整、时间准确、协议兼容**。
检查并修复证书信任链
服务端证书若缺少中间证书(Intermediate CA),客户端就无法构建完整信任路径,Laravel 的 cURL 默认会拒绝连接。
- 用命令行快速验证:
openssl s_client -connect example.com:443 -showcerts,观察输出中是否包含至少两级证书(服务器证书 + 中间证书);若只有一张,说明服务端配置不全 - 在 Laravel 中,可通过
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/fullchain.pem')显式指定含根+中间证书的 PEM 文件(推荐使用 Let's Encrypt 的fullchain.pem) - 如用 Guzzle(Laravel 常用 HTTP 客户端),在配置中设置:
'verify' => '/path/to/fullchain.pem'
校准系统时间并确认 OpenSSL 版本
SSL 证书有效期依赖精确时间。服务器或运行 Laravel 的机器若时间偏差超 5 分钟,证书即被判定无效。
- Linux 下执行:
sudo ntpdate -s time.nist.gov或启用 systemd-timesyncd - 检查 PHP 使用的 OpenSSL 版本:
php -r "print_r(openssl_get_cipher_methods());"或查看phpinfo()中 OpenSSL Version - Laravel 10 要求 OpenSSL ≥ 1.1.1(支持 TLS 1.3 和现代加密套件),低于此版本需升级系统 OpenSSL 或 PHP
适配 TLS 协议版本与禁用不安全选项
老旧 OpenSSL 或强制 TLS 1.0/1.1 的服务端,与默认启用高安全策略的现代环境易冲突。
- 在 cURL 配置中明确指定最低 TLS 版本:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2) - 避免使用
CURLOPT_SSL_VERIFYPEER => false或--insecure—— 这仅用于临时调试,生产环境必须关闭 - 若目标 API 确实只支持 TLS 1.1(极少见),可降级为
CURL_SSLVERSION_TLSv1_1,但应推动对方升级
排查中间设备干扰(CDN / WAF / 反向代理)
请求未到达源站前,可能被 CDN(如 Cloudflare)、WAF 或 Nginx 反向代理拦截并重写 TLS 参数。
- 直连源站 IP 测试(绕过域名解析和 CDN):
curl -v --resolve 'example.com:443:192.0.2.1' https://example.com - 检查代理层是否启用了“严格 SNI 检查”或“TLS 版本白名单”,确保其支持 TLS 1.2+ 且正确透传证书链
- 若使用 Laravel Envoy 或部署脚本,确认部署后未覆盖 Nginx/Apache 的 SSL 配置(尤其
ssl_trusted_certificate或SSLCACertificateFile)











