为何PHP中howsmyssl.com TLS检测结果与cURL STDERR输出不一致?
为什么howsmyssl返回TLS 1.3,但cURL verbose日志显示TLSv1.2?
为了给客户提供支持,我需要检查API请求使用的TLS版本。我用PHP脚本通过cURL向https://www.howsmyssl.com/a/check发送请求,接口返回结果显示使用TLS 1.3,但开启VERBOSE=true后记录的STDERR输出却显示使用TLSv1.2,这是为什么?
cURL响应结果
{"given_cipher_suites":["TLS_AES_256_GCM_SHA384","TLS_CHACHA20_POLY1305_SHA256","TLS_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA","TLS_RSA_WITH_AES_256_GCM_SHA384","TLS_RSA_WITH_AES_128_GCM_SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256","TLS_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_AES_128_CBC_SHA","TLS_EMPTY_RENEGOTIATION_INFO_SCSV"],"ephemeral_keys_supported":true,"session_ticket_supported":false,"tls_compression_supported":false,"unknown_cipher_suite_supported":false,"beast_vuln":false,"able_to_detect_n_minus_one_splitting":false,"insecure_cipher_suites":{},"tls_version":"TLS 1.3","rating":"Probably Okay"}
cURL verbose日志(STDERR输出)
* Trying 34.71.45.200:443... * Connected to www.howsmyssl.com (34.71.45.200) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305 * ALPN, server did not agree to a protocol * Server certificate: * subject: CN=www.howsmyssl.com * start date: Oct 30 02:45:45 2022 GMT * expire date: Jan 28 02:45:44 2023 GMT * subjectAltName: host "www.howsmyssl.com" matched cert's "www.howsmyssl.com" * issuer: C=US; O=Let's Encrypt; CN=R3 * SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. > GET /a/check HTTP/1.1 Host: www.howsmyssl.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.9.0.13) Gecko/2009073022 Firefox/3.5.2 Accept: */* * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Content-Length: 1459 < Access-Control-Allow-Origin: * < Connection: close < Content-Type: application/json < Date: Wed, 09 Nov 2022 08:08:44 GMT < Strict-Transport-Security: max-age=631138519; includeSubdomains; preload < * Closing connection 0
所用PHP代码
$out = fopen('php://temp', 'w+'); $curl = curl_init('https://www.howsmyssl.com/a/check'); curl_setopt_array($curl, array( CURLOPT_RETURNTRANSFER => true, CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.9.0.13) Gecko/2009073022 Firefox/3.5.2', CURLOPT_SSL_VERIFYPEER => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_VERBOSE => true, CURLOPT_STDERR => $out, //CURLOPT_SSLVERSION => CURL_SSLVERSION_MAX_TLSv1_2, //6 = 1.2 | 4 = 1.1.1m )); $curl_result = curl_exec($curl); if ($curl_result) { Kint::dump($curl_result); } rewind($out); curl_close($curl); $TLS_logOutput = stream_get_contents($out); Kint::dump($TLS_logOutput);
问题原因及解决办法
核心原因
日志显示和实际协议版本不符,是因为你的cURL或其依赖的OpenSSL版本不支持TLS 1.3的日志输出,导致verbose模块错误标记了协议版本,但实际握手已经成功协商为TLS 1.3。
验证依据
- howsmyssl的返回结果是服务器端直接检测到的握手协议版本,准确性更高,明确标注了
"tls_version":"TLS 1.3"。 - 响应里的加密套件列表包含TLS 1.3专属套件(如
TLS_AES_256_GCM_SHA384),这些套件只在TLS 1.3握手时才会被使用,进一步证明实际用的是TLS 1.3。
解决办法
- 更新依赖版本:将cURL升级到7.66+、OpenSSL升级到1.1.1+,新版本已经修复了TLS 1.3的日志显示问题,verbose日志会正确输出TLS 1.3。
- 以服务器检测结果为准:如果无法更新依赖,直接参考howsmyssl的返回结果,它比客户端日志更可靠。
内容的提问来源于stack exchange,提问作者mikexmagic
相关产品推荐
相关产品推荐

