指定libcurl域名解析(dns)服务器

因某些运营商会恶意锁死竞争对手的dns,如某动的光猫,直接把电信的114给墙了,导致系统无法通过114这个域名服务器解析域名
这里说明下如何设置libcurl下使用的dns服务器

一 分析

1 下载libcurl包

wget https://curl.haxx.se/download/curl-7.53.0.tar.bz2 tar xjf curl-7.53.0.tar.bz2 cd curl-7.53.0

2 libcurl设置DNS解析服务器

通过如下函数可以设置指定dns域名服务器
curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, “xxx.xxx.xxx.xxx”);

3 libcurl dns部分源码分析

[jenkins@localhost lib]$ grep -r CURLOPT_DNS_SERVERS *
url.c: case CURLOPT_DNS_SERVERS:
进入url.c中,找到CURLOPT_DNS_SERVERS关键字,发现调用Curl_set_dns_servers函数

case CURLOPT_DNS_SERVERS: result = Curl_set_dns_servers(data, va_arg(param, char *)); break;

在当前目录下索索Curl_set_dns_servers函数

[jenkins@localhost lib]$ grep -r Curl_set_dns_servers * asyn-ares.c:CURLcode Curl_set_dns_servers(struct Curl_easy *data, asyn-thread.c:CURLcode Curl_set_dns_servers(struct Curl_easy *data, hostip.h:CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers); hostsyn.c:CURLcode Curl_set_dns_servers(struct Curl_easy *data, url.c: result = Curl_set_dns_servers(data, va_arg(param, char *)); 

发现有三处函数定义asyn-ares.c,asyn-thread.c,hostsyn.c
asyn-thread.c和hostsyn.c中函数原型如下,可以看到在函数中并没有对两个传入参数做任何引用,直接就返回了。

CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers) { (void)data; (void)servers; return CURLE_NOT_BUILT_IN; } 

asyn-ares.c 函数原型如下,可以看到当c-ares version >= 0x010704 时候,会将data和servers两个参数传入ares_set_servers_csv函数中,这个函数应该就是ares中设置dns服务器的接口

CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers) { CURLcode result = CURLE_NOT_BUILT_IN; int ares_result; /* If server is NULL or empty, this would purge all DNS servers * from ares library, which will cause any and all queries to fail. * So, just return OK if none are configured and don't actually make * any changes to c-ares. This lets c-ares use it's defaults, which * it gets from the OS (for instance from /etc/resolv.conf on Linux). */ if(!(servers && servers[0]))  return CURLE_OK;  ares_result = ares_set_servers_csv(data->state.resolver, servers); switch(ares_result) { case ARES_SUCCESS: result = CURLE_OK; break; case ARES_ENOMEM: result = CURLE_OUT_OF_MEMORY; break; case ARES_ENOTINITIALIZED: case ARES_ENODATA: case ARES_EBADSTR: default: result = CURLE_BAD_FUNCTION_ARGUMENT; break; }  (void)data; (void)(ares_result);   return result; }

经过测试发现,curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, “xxx.xxx.xxx.xxx”);函数并没有走asyn-ares.c 中的Curl_set_dns_servers,在libcurl的编译配置文件(arm的buildroot系统),有c-ares的条件编译,发现没有吧c-ares加进去,加进去后测试,发现libcurl使用asyn-ares.c中的函数了

ifeq ($(BR2_PACKAGE_C_ARES),y) LIBCURL_DEPENDENCIES += c-ares LIBCURL_CONF_OPTS += --enable-ares else LIBCURL_CONF_OPTS += --disable-ares endifest_libcurl 

二 测试

为模拟运营商封掉某些域名服务器,可以通过设置iptable 禁用ip
要封停一个IP,使用下面这条命令:
iptables -I INPUT -s ... -j DROP
要解封一个IP,使用下面这条命令:
iptables -D INPUT -s ... -j DROP
禁用114dns服务器
iptables -I INPUT -s 114.114.114.114 -j DROP
禁用可以ping下验证,应该是ping不通的

测试代码见结尾,使用方法
./test_libcurl dns url
第一个参数为要设置的dns, 如114.114.114.114
第二个参数为要访问的url,如www.baidu.com 这里设置比较简单,建议使用baidu,163等,chnshp.lenovo.com.cn 有特殊的设置,这里只验证使用这种方式更改dns是生效的

1 使用114作为dns服务器解析www.baidu.com

这里iptable是没有被禁用的,可以ping通
ping 114.114.114.114
./test_libcurl 114.114.114.114 www.baidu.com
这里写图片描述

2 禁用114 IP,再次测试

发现ping不通,然后按照设置10秒后超时
iptables -I INPUT -s 114.114.114.114 -j DROP
ping 114.114.114.114
./test_libcurl 114.114.114.114 www.baidu.com
这里写图片描述

3 在114被禁用掉的基础上,使用其他dns服务器解析baidu

使用202和路由器dns都是可以的成功的
./test_libcurl 192.168.0.1 www.baidu.com
./test_libcurl 202.106.0.20 www.baidu.com
这里写图片描述

4 在禁用114的基础上,测试设置使用多个dns服务器

./test_libcurl 202.106.0.20,114.114.114.114 www.baidu.com 这里使用114和202,中间以逗号隔开即可,可以成功解析
这里写图片描述

5 在此基础上打开114禁用,测试,通过

iptables -D INPUT -s 114.114.114.114 -j DROP
./test_libcurl 114.114.114.114 www.baidu.com
这里写图片描述

三 结论

综上,在增加c-ares之后,curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, “xx.xx.xx.xx”);这个函数可以设置dns服务器(可以设置多个dns服务器,亲测10个以上都有效),由此可以解决用户因为运营商封IP导致的应用程序升级程序中curl域名解析失败的问题。

四 测试代码test_libcurl.c

#include <stdio.h> #include <curl/curl.h> #include <curl/easy.h> int test(char *URL, char * host) { CURLcode res; CURL *curl; if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { printf("curl_global_init() failed\n"); return -1; curl = curl_easy_init(); if (!curl) { printf("curl_easy_init() failed\n"); curl_global_cleanup(); return 1; } curl_easy_setopt(curl, CURLOPT_URL, URL); curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, host); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_FILETIME, 1L); curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); res = curl_easy_perform(curl); test_cleanup: curl_easy_cleanup(curl); curl_global_cleanup(); return (int)res; } int main(int argc, char *argv[]) { test(argv[2], argv[1]); return 0; } 

原文链接:https://blog.csdn.net/wq3028/article/details/80756039?ops_request_misc=&request_id=&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~koosearch~default-21-80756039-null-null.268%5Ev1%5Ekoosearch&utm_term=%E9%BB%91%E7%BE%A4%E6%99%96%E3%80%81docker%E3%80%81%E5%AE%B9%E5%99%A8%E9%95%9C%E5%83%8F%E3%80%81%E5%9F%9F%E5%90%8D%E6%B3%A8%E5%86%8C%E3%80%81%E5%AE%9D%E5%A1%94%E3%80%81%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E3%80%81nginx%E3%80%81frp%E3%80%81%E5%8A%A8%E6%80%81%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90%E3%80%81NAS%E3%80%81%E7%BE%A4%E6%99%96%E3%80%81%E9%98%BF%E9%87%8C%E4%BA%91%E3%80%81%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90%E3%80%81%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E3%80%81ipv6%E3%80%81ddns%E3%80%81%E8%BD%BB%E9%87%8F%E7%BA%A7%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%81%E9%93%81%E5%A8%81%E9%A9%AC%E3%80%81%E5%A8%81%E8%81%94%E9%80%9A%E3%80%81DSM%E3%80%81DSM6.0%E3%80%81%E7%BE%A4%E6%99%96nas%E3%80%81%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%81%E8%9C%97%E7%89%9B%E6%98%9F%E9%99%85%E3%80%81

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享