You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制PHP cURL使用TLS 1.2而非TLS 1.3?

无法强制PHP cURL使用TLS 1.2,始终使用TLS 1.3

问题现象

尝试通过PHP cURL强制使用TLS 1.2,但无论设置何种CURLOPT_SSLVERSION参数,请求始终使用TLS 1.3。

测试代码

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.howsmyssl.com/a/check");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
// 以下参数均尝试过,结果一致
// also tried *6* => same response.
// also tried *5* => same response.
// also tried *4* => same response.
// also tried *3* => same response.
// also tried *2* => same response.
// also tried *1* => same response.
// also tried *0* => same response.

// 尝试CURL_SSLVERSION_MAX_TLSv1_2时触发错误:Undefined constant "CURL_SSLVERSION_MAX_TLSv1_2"

$response = curl_exec($ch);
curl_close($ch);
$tlsVer = json_decode($response, true);
echo "<h1>Your TSL version is: <u>" . ($tlsVer['tls_version'] ?: 'no TLS support') . "</u></h1>";

执行结果

<h1>Your TSL version is: <u>TLS 1.3</u></h1>

环境信息

基础版本

  • Curl版本:7.87.0
  • OpenSSL版本:OpenSSL 1.0.2k-fips 26 Jan 2017
  • PHP版本:8.2.2

phpinfo()细节

OpenSSL

  • OpenSSL支持:已启用
  • OpenSSL库版本:OpenSSL 1.0.2k-fips 26 Jan 2017
  • OpenSSL头版本:OpenSSL 1.0.2k 26 Jan 2017
  • OpenSSL默认配置:/etc/pki/tls/openssl.cnf

cURL

  • cURL支持:已启用
  • cURL信息:7.87.0
  • 特性:
    • AsynchDNS: 是
    • CharConv: 否
    • Debug: 否
    • GSS-Negotiate: 否
    • IDN: 否
    • IPv6: 是
    • krb4: 否
    • Largefile: 是
    • libz: 是
    • NTLM: 是
    • NTLMWB: 是
    • SPNEGO: 是
    • SSL: 是
    • SSPI: 否
    • TLS-SRP: 否
  • 支持协议:dict, file, ftp, ftps, gopher, gophers, http, https, imap, imaps, ldap, ldaps, mqtt, pop3, pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
  • 主机:x86_64-redhat-linux-gnu
  • SSL版本:NSS/3.79
  • ZLib版本:1.2.7
  • libSSH版本:libssh2/1.10.0

补充:服务器之前使用curl 7.29.0,现已更新至7.87.0。


原因分析与解决方案

核心原因

从phpinfo()的cURL部分可以看到,当前cURL使用的SSL库是NSS/3.79,而非预期的OpenSSL 1.0.2k。OpenSSL 1.0.2k本身不支持TLS 1.3,但NSS 3.79支持,且cURL编译时绑定了NSS库,导致TLS版本控制逻辑受NSS影响。另外,CURL_SSLVERSION_MAX_TLSv1_2常量在当前PHP版本中未定义,直接使用会报错。

解决方案

  1. 通过加密套件限制强制使用TLS 1.2
    NSS对CURLOPT_SSLVERSION的支持存在兼容性问题,可通过指定仅TLS 1.2支持的加密套件,让cURL因无法匹配TLS 1.3套件而降级:

    curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384");
    
  2. 重新编译cURL绑定OpenSSL
    若需彻底解决,可重新编译cURL使其绑定OpenSSL而非NSS:

    • 下载cURL 7.87.0源码
    • 编译时指定OpenSSL路径:./configure --with-openssl=/path/to/openssl --prefix=/usr/local/curl
    • 安装后重新编译PHP的cURL扩展,链接新的cURL库
  3. 检查系统级SSL配置
    部分系统全局配置(如NSS配置文件或/etc/pki/tls/openssl.cnf)会默认启用TLS 1.3,可检查配置中的MinProtocol或Protocol字段,将其设置为TLSv1.2。

内容的提问来源于stack exchange,提问作者Atakan Akbulut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:05:20