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

时间:2019-06-05 01:10:29

标签: c openssl libcurl

我有使用OpenSSL后端构建的libcurl。我想将SNI设置为某些指定的字符串。我可以找到的方法是使用函数SSL_set_tlsext_host_name,该函数接受SSL *实例和一个字符串,然后对其进行设置。 (请参阅https://stackoverflow.com/a/5113466/3754125

但是,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,而无需触摸解析器。

1 个答案:

答案 0 :(得分:1)

如果您要“伪造” SNI,则可以使用CURLOPT_RESOLVECURLOPT_CONNECT_TO来达到相同的最终目标。

CURLOPT_RESOLVE示例

在127.0.0.1上运行HTTPS服务器,但使curl在连接到它时认为它是example.com(因此它将以SNI的形式发送到Host:标头中)

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上运行dev 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);