C++ 无法使用OpenSSL 1.1.1从ClientHello检索服务器名称(SNI)

C++ 无法使用OpenSSL 1.1.1从ClientHello检索服务器名称(SNI),c++,ssl,openssl,tls1.2,sni,C++,Ssl,Openssl,Tls1.2,Sni,在我正在运行的服务器上(使用OpenSSL 1.1.1d),我尝试通过以下回调从ClientHello消息中提取服务器名称(SNI)扩展名: 调用SSL\u client\u hello\u get0\u ext,使用中的TLSEXT\u TYPE\u server\u name类型 使用TLSEXT\u NAMETYPE\u host\u name调用SSL\u get\u servername 然而,似乎什么都不起作用,SNI要么是空的,要么是垃圾 我注意到的一件事是,只有在完成Clie

在我正在运行的服务器上(使用OpenSSL 1.1.1d),我尝试通过以下回调从ClientHello消息中提取服务器名称(SNI)扩展名:

  • 调用
    SSL\u client\u hello\u get0\u ext
    ,使用中的
    TLSEXT\u TYPE\u server\u name
    类型
  • 使用
    TLSEXT\u NAMETYPE\u host\u name
    调用
    SSL\u get\u servername
然而,似乎什么都不起作用,SNI要么是空的,要么是垃圾

我注意到的一件事是,只有在完成ClientHello回调之后,我才能够提取它,但此时为时已晚。 有人遇到过类似的问题吗

下面附上一个演示如何检索SNI的最小代码示例:

int
my_server::client_hello_cb(SSL *ssl, int *al, void *arg)
{
    my_server* server = static_cast<my_server*>(SSL_get_app_data(ssl));
    const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);

    server->set_client_sni(sni);
    return 0;
}

void
my_server::create()
{
    SSL* ssl = SSL_new(ctx_);
    SSL_set_app_data(ssl, this);

    BIO* rbio = BIO_new(BIO_s_mem());
    BIO* wbio = BIO_new(BIO_s_mem());
    SSL_set_bio(ssl, rbio, wbio);

    SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());

    SSL_CTX_set_ecdh_auto(ctx, 1);
    SSL_CTX_set_client_hello_cb(ctx, client_hello_cb, nullptr);
}
int
my_server::client_hello_cb(SSL*SSL,int*al,void*arg)
{
my_server*server=static_cast(SSL_get_app_data(SSL));
const char*sni=SSL\u get\u servername(SSL,TLSEXT\u NAMETYPE\u host\u name);
服务器->设置客户端sni(sni);
返回0;
}
无效的
我的服务器::创建()
{
SSL*SSL=SSL_新(ctx_u);
SSL\u set\u app\u数据(SSL,this);
BIO*rbio=BIO_new(BIO_s_mem());
BIO*wbio=BIO_new(BIO_s_mem());
SSL_set_bio(SSL、rbio、wbio);
SSL_CTX*CTX=SSL_CTX_new(TLS_server_method());
SSL\u CTX\u set\u ecdh\u auto(CTX,1);
SSL_CTX_set_client_hello_cb(CTX,client_hello_cb,nullptr);
}
特别感谢您清理了这些东西

必须直接从服务器名称回调调用
SSL\u get\u servername
,否则无法解决原始问题


相反,可以使用
SSL\u client\u hello\u get0\u ext直接从客户端hello回调手动解析服务器名称扩展名。

请为您的问题提供解决方案。由于它的行为与OpenSSL测试代码不同,这表明您的代码中存在一些本质的不同之处。@SteffenUllrich很遗憾,我无法共享源代码。但是,主流程是在我的服务器上注册到“SSL\u CTX\u set\u client\u hello\u cb”,并在调用回调时调用“SSL\u get\u servername”(返回null)。EDI没有要求您共享原始源代码。事实上,这可能是太多的代码无法查看。相反,我要求您创建一些最小的代码示例,其他人可以使用这些示例来重现问题。一种常见的方法是将原始代码剥离到再现问题所需的最低限度。另一种方法是根据您在问题中的描述创建一些最小的代码-如果这还不足以重新创建问题,则您的问题缺少基本的细节。@SteffenUllrich添加了一些演示基本流程的代码示例,希望它可能会有所帮助可能是因为
SSL\u get\u servername
在clienthello回调中不起作用,因为它更适合稍后出现的(过时的)
tlsext\u servername\u回调。但是您特别提到的是
SSL\u client\u hello\u get0\u ext
即使在OpenSSL测试代码中使用了它,也无法工作。请在示例代码中使用它,并提供关于它返回的声明“垃圾”的更多详细信息。