带有 OpenSSL 后端的 libcurl 中的假服务器名称指示 (SNI)

fake Server Name indication (SNI) in libcurl with OpenSSL backend

我有使用 OpenSSL 后端构建的 libcurl。我想将 SNI 设置为某个指定的字符串。我能找到的方法是使用函数 SSL_set_tlsext_host_name,它接受 SSL * 实例和一个字符串,然后设置它。 (参见 )

但是 curl_easy 没有回调来检索 SSL* 实例。有其他方法吗?

更多背景信息: 在我的环境中,我必须使用 CURLOPT_RESOLVE 将 FQDN 解析为 IPv4。 有 FQDN:const char *fqdn fqdn 应解析为的 IPv4:uint32_t ipv4 假 SNI:const char *sni 要点看起来像:

CURL *ez;
char buf[ENOUGH];
struct curl_slist *resolver;
/* ... */
snprintf(buf, sizeof(buf), "%s:%d:%d.%d.%d.%d", fqdn, port, IP(IPv4));
resolver = curl_slist_append(NULL, buf);
curl_easy_setopt(ez, CURLOPT_RESOLVE, resolver);

在此之后我需要在不接触解析器的情况下将 SNI 设置为伪造的 SNI。

如果您想要 "fake" SNI,那么 CURLOPT_RESOLVECURLOPT_CONNECT_TO 是达到相同最终目标的可用选项。

CURLOPT_RESOLVE 例子

运行 127.0.0.1 上的 HTTPS 服务器,但让 curl 在连接到它时认为它是 example.com(因此它将其作为 SNI 发送并在 Host: header)

CURL *curl;
struct curl_slist *host = NULL;
host = curl_slist_append(NULL, "example.com:443:127.0.0.1");

curl = curl_easy_init();
if(curl) {
  curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
  curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");

  curl_easy_perform(curl);

  /* always cleanup */
  curl_easy_cleanup(curl);
}

curl_slist_free_all(host);

CURLOPT_CONNECT_TO 例子

运行 主机名 server1.example.com 上的开发 HTTPS 服务器,但您希望 curl 连接到它,认为它是 www.example.org 服务器。

CURL *curl;
struct curl_slist *connect_to = NULL;
connect_to = curl_slist_append(NULL, "www.example.org::server1.example.com:");

curl = curl_easy_init();
if(curl) {
  curl_easy_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
  curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.org");

  curl_easy_perform(curl);

  /* always cleanup */
  curl_easy_cleanup(curl);
}

curl_slist_free_all(connect_to);