如何强制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版本中未定义,直接使用会报错。
解决方案
通过加密套件限制强制使用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");重新编译cURL绑定OpenSSL
若需彻底解决,可重新编译cURL使其绑定OpenSSL而非NSS:- 下载cURL 7.87.0源码
- 编译时指定OpenSSL路径:
./configure --with-openssl=/path/to/openssl --prefix=/usr/local/curl - 安装后重新编译PHP的cURL扩展,链接新的cURL库
检查系统级SSL配置
部分系统全局配置(如NSS配置文件或/etc/pki/tls/openssl.cnf)会默认启用TLS 1.3,可检查配置中的MinProtocol或Protocol字段,将其设置为TLSv1.2。
内容的提问来源于stack exchange,提问作者Atakan Akbulut
相关产品推荐
相关产品推荐

