使用OpenSSL后端在libcurl中伪造服务器名称指示(SNI)
我使用OpenSSL后端构建了libcurl。我想将SNI设置为某个指定的字符串。我可以找到的方法是使用函数使用OpenSSL后端在libcurl中伪造服务器名称指示(SNI),c,openssl,libcurl,C,Openssl,Libcurl,我使用OpenSSL后端构建了libcurl。我想将SNI设置为某个指定的字符串。我可以找到的方法是使用函数SSL\u set\u tlsext\u host\u name,它获取SSL*实例和一个字符串,然后设置它。(见附件) 但是,curl\u easy没有回调来检索SSL*实例。有没有其他办法 更多背景: 在我的环境中,我必须使用CURLOPT_RESOLVE将FQDN解析为IPv4。 有FQDN:const char*FQDN fqdn应解析为:uint32\t IPv4的IPv4 假S
SSL\u set\u tlsext\u host\u name
,它获取SSL*
实例和一个字符串,然后设置它。(见附件)
但是,curl\u easy没有回调来检索SSL*
实例。有没有其他办法
更多背景:
在我的环境中,我必须使用CURLOPT_RESOLVE
将FQDN解析为IPv4。
有FQDN:const char*FQDN
fqdn
应解析为:uint32\t IPv4的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。如果要“假”SNI,则CURLOPT\u RESOLVE
或CURLOPT\u CONNECT\u to
是实现相同最终目标的可用选项
CULLOPT_解析示例
在127.0.0.1上运行一个HTTPS服务器,但当它连接到它时,让curl认为它是example.com
(因此它将其作为SNI发送,并在主机:
标题中发送)
CURLOPT_连接到示例
在主机名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);
SSL\u CTX\u set\u tlsext\u servername\u回调
可能会起作用。如果有效,我会更新。如果有效,请自己回答问题:)@AnttiHaapala,不幸的是,我的解决方案不起作用。它只适用于服务器,但在我的情况下,我是客户机。使用CURLOPT_RESOLVE
或CURLOPT_CONNECT_TO
如何准确地实现这一点?我已经在使用CURLOPT_RESOLVE
将FQDN解析为IPv4。感谢您在回答中包含代码。然而,这对我来说不起作用。我正在使用CURLOPT\u RESOLVE
将FQDN解析为IPv4(看起来像curl\u slist\u append(NULL,“www.example.org:10443:172.18.27.161”)
(我必须这样做,因为我有一个特定的API将FQDN解析为IPv4,否则curl无法解析)。我试图注入SNI的字符串实际上是一个令牌,服务器使用它来标识应该如何调度连接。该令牌看起来像这样:tYqxjS6ntrqmPtBwUli1
。因此,如果我想用CURLOPT_RESOLVE
伪造SNI,我无法解析fqdn!好吧,但是你不再做HTTPS了。。。这没什么错,但是curl专注于讨论我们使其支持的特定协议。实际上我在做https!它类似于curl\u easy\u setopt(ez\u h,CURLOPT\u URL,“https://www.example.org:10443/api/entry/point)
。你是在暗示我不能在https中伪造SNI吗?再考虑一下这个解决方案,它对我的案例有效<代码>ipv4=获取ipv4(fqdn);snprintf(解析项,sizeof(解析项),%s:%s:%d.%d.%d.%d),假sni,端口,IP(ipv4));resolve_list=curl_slist_add(NULL,resolve_条目);snprintf(url,sizeof(url),“https://%s:%s/%s”,假sni,端口,api入口点)唯一的问题是我必须将referer设置为fqdn
。
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);