…来弥补我们无法控制的破损的DNS服务器。
我们的问题:我们部署embedded式设备,收集各种传感器数据,主要是纯IPv4站点。 有些网站的networking维护能力较差,例如configuration不当或以其他方式破坏的DNScaching和/或防火墙,或者完全忽略AAAA查询,或者以破坏的应答(例如,错误的源IP)对其进行响应。 作为设施部门的外部供应商,我们几乎不会影响(有时是不情愿的)IT部门。 他们很快修复DNS服务器/防火墙的机会很小。
对我们的设备的影响是,对于每个gethostbyname(),进程必须等待,直到AAAA查询超时,此时一些进程已经完成超时连接尝试。
我正在寻找解决scheme,是…
最明显的解决scheme是configurationparsing器库,例如通过/ etc / { resolv , nsswitch , gai } .conf来不查询AAAAlogging。 像这里build议的resolv.conf选项no-inet6
将正是我正在寻找的。 不幸的是,它并没有实现,至less在我们的系统上(Debian 7上的libc6-2.13-38 + deb7u4; Ubuntu 14.04上的libc6-2.19-0ubuntu6.3)
那么怎么样? 人们发现在SF和其他地方提出了以下方法,但是它们不工作:
sysctl -w net.ipv6.conf.all.disable_ipv6=1
列入黑名单。 ( 出于好奇:为什么parsing器要求禁用IPv6的AAAA? ) options inet6
。 这不是第一个, inet6
现在只是默认启用。 options single-request
。 这只能确保A和AAAA查询顺序而不是并行地完成 precedence
。 这不会影响DNS查询,只会处理多个答复。 另类丑陋的想法:
请注意,SE上也有类似的相关问题。 我的问题在阐述我试图解决的实际问题方面有所不同,因为它列出了明确的要求,因为它列出了一些经常提出的非工作解决scheme,并且因为它不是特定于单个应用程序。 在这个讨论之后 ,我发布了我的问题。
停止使用gethostbyname()
。 您应该使用getaddrinfo()
,而应该已经有多年了。 手册页甚至提醒你这一点。
gethostbyname *(),gethostbyaddr *(),herror()和hstrerror()函数已经过时。 应用程序应该使用getaddrinfo(3),getnameinfo(3)和gai_strerror(3)。
下面是C语言中的一个快速示例程序,它演示了仅查找Alogging的名称和Wireshark捕获,显示只有 Alogging查找通过networking。
尤其是,如果只需要Alogging查找,则需要将ai_family
设置为AF_INET
。 本示例程序仅打印返回的IP地址。 有关如何进行传出连接的更完整示例,请参阅getaddrinfo()
手册页。
在Wireshark捕获中 ,172.25.50.3是本地DNSparsing器; 捕获在那里,所以你也看到它的外向查询和答复。 请注意只有一个Alogging被请求。 没有做过AAAA查询。
#include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <stdlib.h> #include <netdb.h> #include <stdio.h> int main(void) { struct addrinfo hints; struct addrinfo *result, *rp; int s; char host[256]; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; s = getaddrinfo("www.facebook.com", NULL, &hints, &result); if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); exit(EXIT_FAILURE); } for (rp = result; rp != NULL; rp = rp->ai_next) { getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST); printf("%s\n", host); } freeaddrinfo(result); }
如有疑问,请转到源代码! 所以,让我们看看… gethostbyname()看起来很有趣。 这个描述了我们所看到的:先尝试IPv6,然后回到IPv4,如果你没有得到你喜欢的答案的话。 这是什么RES_USE_INET6
标志? 追溯它,它来自res_setoptions() 。 这是读取resolv.conf
地方。
而….这是我的想法。 如果不是在resolv.conf
,我完全不清楚RES_USE_INET6
是如何设置的。
您可以使用BIND作为本地parsing器,它有一个选项来过滤AAAA:
https://kb.isc.org/article/AA-00576/0/Filter-AAAA-option-in-BIND-9-.html
您是否尝试设置PDNS-recursor,将其设置在/etc/resolv.conf中,并拒绝“AAAA”查找? 使用诸如query-local-address6=