【问题标题】:fake Server Name indication (SNI) in libcurl with OpenSSL backend带有 OpenSSL 后端的 libcurl 中的虚假服务器名称指示 (SNI)
【发布时间】:2019-10-20 12:40:59
【问题描述】:

我使用 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 IPv4 fqdn 应解析为: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。

【问题讨论】:

  • SSL_CTX_set_tlsext_servername_callback 可能会起作用。如果它有效,我会更新。
  • 如果可行,请自己回答问题:)
  • @AnttiHaapala,不幸的是,我的解决方案不起作用。它仅适用于服务器,但在我的情况下,我是客户端。

标签: c openssl libcurl


【解决方案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 上运行开发 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);

【讨论】:

  • 如何使用CURLOPT_RESOLVECURLOPT_CONNECT_TO 精确地做到这一点?我已经在使用CURLOPT_RESOLVE 将 FQDN 解析为 IPv4。
  • 感谢您在答案中包含代码。但是,这对我不起作用。我正在使用CURLOPT_RESOLVE 将 FQDN 解析为 IPv4(看起来像 curl_slist_append(NULL, "www.example.org:10443:172.18.27.161"))(我必须这样做,因为我有一个特定的 API 可以将 FQDN 解析为 IPv4,否则 curl 无法解析)。我试图注入 SNI 的字符串实际上是服务器用来识别它应该如何分派连接的令牌。令牌看起来像这样:tYqxjS6ntrqmPtBwUli1。所以如果我想用CURLOPT_RESOLVE 伪造 SNI,我无法解析 fqdn!
  • 好的,但是你不再使用 HTTPS...这没什么错,但 curl 专注于讨论我们让它支持的特定协议。
  • 其实我在做https!类似于curl_easy_setopt(ez_h, CURLOPT_URL, "https://www.example.org:10443/api/entry/point")。您是在暗示我不能在 https 中伪造 SNI?
  • 重新考虑这个解决方案,它适用于我的情况。 ipv4=getipv4(fqdn); snprintf(resolve_entry, sizeof(resolve_entry), "%s:%s:%d.%d.%d.%d", fake_sni, port, IP(ipv4)); resolve_list = curl_slist_add(NULL, resolve_entry);snprintf(url, sizeof(url), "https://%s:%s/%s", fake_sni, port, api_entry_point); 唯一的问题是我必须将引用者设置为 fqdn
猜你喜欢
  • 2020-05-08
  • 1970-01-01
  • 2017-04-13
  • 2012-09-03
  • 2017-05-23
  • 2013-11-03
  • 2011-07-04
  • 1970-01-01
相关资源
最近更新 更多