1.背景
1.苹果最近调整了HTTP连接的思路,要求iOS开发代码中所有的http连接都必须使用,https安全连接方式。
2.在实现HTTP服务中,会有种VIP的保障逻辑。在域名解析失败(DNS劫持是其中一种情况)而无法连接时候,会内置ip地址,保证在最坏的情况下,可以连通服务。
那么问题来了,HTTPS直接使用HOST为ip地址的时候,是无法正确使用SSL校验安全证书的,因为证书和域名绑定。
2.环境
curl组件c实现库,iOS开发工程
3.方案
实现方式只是在现有curl组件实现的,http逻辑逻辑基础上补充。具体完整curl实现http请求逻辑,待补充。
原理:通过IP直接访问网站,解决DNS劫持问题。DNS劫持中,对于HTTPS请求,有SSL校验安全证书的过程,这个时候HOST参数对应的域名是被绑定到证书上,进行安全校验,而IP是无法通过校验的。这个时候只有在SSL校验之前修改HOST参数为实际绑定的域名,才能完成SSL安全校验。这个时候就涉及到CURL组件里面setOption(CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);设置。找到在SSL校验之前修改参数的时机,具体实现如下。
添加代码以及调试逻辑主要是在初始化时候添加如下三行代码:
setOption(CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
setOption(CURLOPT_DEBUGFUNCTION, my_trace);
setOption(CURLOPT_VERBOSE, 1L);
sslctx_function 和 my_trace 方法逻辑如下:
static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
{
if (curl) {XXX
struct curl_slist *list = NULL;
list = curl_slist_append(list, "Host: XXX.XXX.XXX.XXX:8888");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
}
/* all set to go */
return CURLE_OK;
}
static int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)
{
const char *text;
(void)handle; /* prevent compiler warning */
(void)userp;
char buf[1024] = {0};
snprintf(buf, size, "%s type %d", data, type);
mylog("%s", buf);
switch (type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
default: /* in case a new one is introduced to shock us */
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "=> Send SSL data";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
}
if (text)
{
mylog("== %s", text);
}
// dump(text, stderr, (unsigned char *)data, size);
return 0;
}
4.结论
5.参考
curl中日志追踪实现 -- https://curl.haxx.se/libcurl/c/CURLOPT_DEBUGFUNCTION.html
实现思路参考 -- https://github.com/tencentyun/httpdns-ios-sdk