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

OpenSSL/C++:ClientHello无法生成SNI扩展的问题排查

问题原因

你代码里的核心问题是手动创建的SSL对象和BIO_new_ssl_connect生成的BIO内部的SSL实例完全独立。你调用SSL_set_tlsext_host_name设置的是自己创建的那个SSL,但实际发起TLS连接时,BIO用的是它自己内部生成的SSL对象,所以你的SNI配置根本没生效。

修正方案

有两种可行的修正方式:

方式一:从BIO中获取内部SSL对象并设置SNI

使用BIO_get_ssl从已创建的BIO中提取出实际使用的SSL实例,再对它设置SNI:

#include <openssl/ssl.h>
#include <openssl/bio.h>

int main()
{
    SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
    BIO* bio = BIO_new_ssl_connect(ctx);
    BIO_set_conn_hostname(bio, "demo.piesocket.com:443");
    
    // 从BIO中获取实际使用的SSL对象
    SSL* ssl = nullptr;
    BIO_get_ssl(bio, &ssl);
    if (ssl != nullptr) {
        SSL_set_tlsext_host_name(ssl, "demo.piesocket.com");
    }
    
    BIO_do_connect(bio);
    BIO_free_all(bio);
    SSL_CTX_free(ctx);
    return 0;
}

方式二:手动关联BIO与SSL对象

不使用BIO_new_ssl_connect,而是手动创建TCP BIO和SSL对象并关联,这样可以完全控制SSL实例:

#include <openssl/ssl.h>
#include <openssl/bio.h>

int main()
{
    SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
    SSL* ssl = SSL_new(ctx);
    // 创建TCP连接BIO
    BIO* bio = BIO_new_connect("demo.piesocket.com:443");
    // 将SSL与BIO关联
    SSL_set_bio(ssl, bio, bio);
    
    SSL_set_tlsext_host_name(ssl, "demo.piesocket.com");
    SSL_connect(ssl);
    
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    return 0;
}
验证说明

修正后再用Wireshark抓包,ClientHello数据包里就会出现Extension: server_name条目,和openssl s_client demo.piesocket.com:443的行为一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 10:20:36