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

LibCurl code:35排查:curl -k生效但C++代码SSL连接失败

问题:LibCurl SSL/TLS握手失败(已模拟curl -k仍无效)

执行C++脚本时遇到错误:LibCurl code:35 - Message: schannel: failed to receive handshake, SSL/TLS connection failed。已在代码中设置curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L)和curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L)以模拟curl命令的-k选项,但直接在命令行使用curl -k却能正常运行。

添加curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L)后的输出如下:

Trying x.x.x.x:443...

Connected to x.x.x.x (x.x.x.x) port 443 (#0)

schannel: disabled automatic use of client certificate

schannel: using IP address, SNI is not supported by OS.

schannel: failed to receive handshake, SSL/TLS connection failed

Closing connection 0

补充说明:报错的服务器无需认证,以下示例代码(与项目中使用的CURL选项一致,以www.example.com为例)也会返回相同错误:

#include <curl/curl.h>
#include <iostream>

int main() {
    CURL *curl;
    CURLcode res;
    char errbuf[CURL_ERROR_SIZE];

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000);

        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << errbuf << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    return 0;
}

请问还需添加哪些CURL选项以完全模拟curl -k的行为?


解决方案

从verbose输出的schannel: using IP address, SNI is not supported by OS可以看出,问题出在Windows schannel SSL库的配置细节上——命令行curl默认处理了这些逻辑,而代码中缺少对应的选项。可以尝试添加以下选项来匹配curl -k的完整行为:

  • 指定TLS版本范围:部分服务器仅支持特定版本的TLS,代码默认的版本协商可能失效。添加以下选项让curl自动协商最高可用的TLS版本:

    curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_MAX_ALLOWED);
    

    若仍失败,可尝试强制指定TLS 1.2或1.3:

    // 强制使用TLS 1.2
    curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
    
  • 禁用证书吊销检查:Windows下schannel默认会执行证书吊销状态检查,即使关闭了证书验证,该检查也可能导致握手失败。添加选项禁用该检查:

    curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
    
  • 强制启用SNI:虽然输出提示OS不支持SNI,但编译的libcurl版本可能支持强制开启该功能,尝试添加:

    curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_SNI, 1L);
    
  • 检查libcurl版本一致性:确保代码链接的libcurl版本与命令行使用的curl版本一致,旧版本libcurl对schannel的支持可能存在缺陷,升级到最新版本可解决部分兼容性问题。

修改后的示例代码:

#include <curl/curl.h>
#include <iostream>

int main() {
    CURL *curl;
    CURLcode res;
    char errbuf[CURL_ERROR_SIZE];

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000);
        
        // 添加选项匹配curl -k行为
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_MAX_ALLOWED);
        curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
        curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_SNI, 1L);

        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << errbuf << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:16:03