gpt4 book ai didi

c - 使用 SNI 在一个盒子中提供多个域

转载 作者:太空狗 更新时间:2023-10-29 15:24:14 26 4
gpt4 key购买 nike

我在 FreeBSD-8.2 中使用 OpenSSL 0.9.8q。我的系统上有 3 个虚拟主机,我想实现 SNI 以在一台服务器中为所有 3 个虚拟主机提供服务。

我有 3 个单独的证书,每个证书一个,在我的 ssl-server 代码中,我必须以某种方式找出客户端请求的域名,并基于此使用适当的证书文件。为此,我编写了一个名为 get_ssl_servername_cb 的函数,并将其作为回调函数传递给 SSL_CTX_set_tlsext_servername_callback。这样,在回调函数中我可以获得客户端请求的域名。

但我的问题是,这个回调函数是在执行SSL_accept函数之后执行的,但是我必须在使用SSL_new命令之前选择并使用适当的证书,这在执行 SSL_accept 之前。

所以我的问题是,如何为 SNI 使用 SSL_CTX_set_tlsext_servername_callback 函数?

最佳答案

but my problem is, this callback function is being executed after execution of "SSL_accept" function, but I have to choose and use the appropriate certificate before using "SSL_new" command, which is way before execution of SSL_accept.

当你启动你的服务器时,你提供了一个默认值 SSL_CTX .这用于非 SNI 客户端,如 SSLv3 客户端和不使用 SNI 的 TLS 客户端(如 Windows XP)。这是必需的,因为在这种情况下不会调用回调。

这里有一些使用 OpenSSL 的 s_client 的行为的例子。 .模拟非 SNI 客户端,以便您的 get_ssl_servername_cb 没有调用,问题:

  • openssl s_client -connect localhost:8443 -ssl3 # SNI 添加到 TLSv1
  • openssl s_client -connect localhost:8443 -tls1 # Windows XP 客户端

模拟 SNI 客户端,以便您的 get_ssl_servername_cb 调用,问题:

  • openssl s_client -connect localhost:8443 -tls1 -servername localhost

您还可以通过添加 -CAfile 来避免证书验证错误.这是我的一个测试脚本(用于在 localhost 上测试 DSS/DSA 证书):

printf "GET / HTTP/1.1\r\n\r\n" | /usr/local/ssl/bin/openssl s_client \
-connect localhost:8443 -tls1 -servername localhost \
-CAfile pki/signing-dss-cert.pem

so my question is, how can I use "SSL_CTX_set_tlsext_servername_callback" function for SNI?

请参阅 <openssl dir>/apps/s_server.c 处的 OpenSSL 源代码;或查看 How to implement Server Name Indication(SNI) on OpenSSL in C or C++? .

在你的get_ssl_servername_cb (用 SSL_CTX_set_tlsext_servername_callback 设置),您检查服务器名称。出现两种情况之一:您已经有一个 SSL_CTX服务器名称,或者您需要创建一个 SSL_CTX服务器名称。

一旦你获取了 SSL_CTX从缓存或创建一个新的 SSL_CTX ,然后使用 SSL_set_SSL_CTX在上下文中交换。在 OpenSSL 源文件中有一个在新上下文中交换的示例。查看 s_server.c 的代码(在 <openssl dir>/apps/s_server.c 中)。追踪 ctx2 ,

这是我的一个项目中的样子。 IsDomainInDefaultCert确定请求的服务器名称是否由默认服务器证书提供。如果没有,GetServerContext获取所需的 SSL_CTX . GetServerContext从应用程序级缓存中提取所需的证书;或创建它并将其放入应用程序级缓存(GetServerContext 还在 SSL_CTX 上断言一个引用计数,因此 OpenSSL 库不会从应用程序下删除它)。

static int ServerNameCallback(SSL *ssl, int *ad, void *arg)
{
UNUSED(ad);
UNUSED(arg);

ASSERT(ssl);
if (ssl == NULL)
return SSL_TLSEXT_ERR_NOACK;

const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
ASSERT(servername && servername[0]);
if (!servername || servername[0] == '\0')
return SSL_TLSEXT_ERR_NOACK;

/* Does the default cert already handle this domain? */
if (IsDomainInDefCert(servername))
return SSL_TLSEXT_ERR_OK;

/* Need a new certificate for this domain */
SSL_CTX* ctx = GetServerContext(servername);
ASSERT(ctx != NULL);
if (ctx == NULL)
return SSL_TLSEXT_ERR_NOACK;

/* Useless return value */
SSL_CTX* v = SSL_set_SSL_CTX(ssl, ctx);
ASSERT(v == ctx);
if (v != ctx)
return SSL_TLSEXT_ERR_NOACK;

return SSL_TLSEXT_ERR_OK;
}

在上面的代码中,adarg是未使用的参数。我不知道是什么ad因为我不使用它。 arg可用于将上下文传递给回调。我不使用 arg要么,但是s_server.c使用它来打印一些调试信息(arg 是指向 BIO 的指针,与 stderr(以及其他一些)相关联,IIRC)。


为了完整性,SSL_CTX被引用计数并且它们可以被重新使用。一个新创建的 SSL_CTX计数为 1,委托(delegate)给 OpenSSL 内部缓存机制。当你递上 SSL_CTXSSL对象,计数递增到 2。当 SSL对象调用 SSL_CTX_freeSSL_CTX 上,该函数将减少引用计数。如果上下文过期且引用计数为 1,则 OpenSSL 库会将其从其内部缓存中删除。

关于c - 使用 SNI 在一个盒子中提供多个域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22373332/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com