macOS下如何强制指定res_query(resolver(3))使用的DNS服务器?相关调试问题求助
macOS下如何强制指定res_query(resolver(3))使用的DNS服务器?相关调试问题求助
我最近在macOS上用resolver(3)套件里的res_query做程序化DNS查询,正常环境下跑起来没问题,但一连接公司VPN就直接超时卡壳,折腾好几天都没找到根因,想求助下各位大佬!
先跟大家说下我目前的排查情况和核心疑惑:
- 我怀疑问题出在res_query选了错误的DNS服务器,但完全摸不清怎么控制它的服务器选择逻辑,调试起来特别费劲。同主机上的Linux和FreeBSD虚拟机不管连不连VPN都能正常查询,所以应该不是纯VPN配置的锅——但公司VPN的配置可能有某些和macOS不兼容的细节,我又找不到具体是啥,没法提交有效的问题报告让IT修复。
- 奇怪的是,用
dig或者host命令在macOS上不管连不连VPN都能正常查DNS,说明肯定有配置空间,但res_query的man页里完全没提这些配置项。我知道dig/host和macOS的解析机制关系复杂,但至少说明macOS本身是能正确处理的,只是res_query没用到正确的配置。 - 我给
_res.options加上了RES_DEBUG标记,能看到查询请求发往的DNS服务器,但这个服务器列表和scutil --dns输出的完全对不上,更坐实了res_query选了错误服务器的猜测。 - 最诡异的是抓包发现:DNS请求确实发出去了,而且服务器也返回了正确的响应,但
res_send内部调用的recvfrom居然返回了「invalid argument」错误——这说明问题可能根本不是网络层面的,而是res_query和macOS的DNS框架交互出了问题? - 我试过按resolver(3) man页的提示,用
LOCALDOMAIN环境变量来调整搜索策略,但man页只说用空格分隔的令牌,连个例子都没有,我试了各种值都没效果,感觉这部分文档缺了关键细节。 - 也看了不少类似问题,比如针对LAN域名覆盖的、自定义DNS服务器的,但要么场景不匹配,要么解决方案太“玄学”,没法直接套用到我的问题上。
下面是我用来测试的最小代码,编译运行命令也附上了:
// 编译命令:cc -Wall -g -o mini-dns-lookup mini-dns-lookup.c -lresolv // 运行命令:./mini-dns-lookup #include <stdio.h> #include <stdlib.h> #include <resolv.h> #include <sys/types.h> #include <errno.h> #include <string.h> int main(int argc, char** argv) { res_init(); _res.options |= RES_DEBUG; uint8_t buf[NS_PACKETSZ]; errno = 0; int res_len = res_query("www.google.com", ns_c_in, ns_t_a, buf, sizeof(buf)); ns_msg msg; ns_rr rr; ns_initparse(buf, res_len, &msg); int nmsg = ns_msg_count(msg, ns_s_an); for (int recnum=0; recnum<nmsg; recnum++) { if (ns_parserr(&msg, ns_s_an, recnum, &rr)) { fprintf(stderr, "ns_parserr: error parsing record %d: %s\n", recnum, strerror(errno)); exit(1); } char dispbuf[4096]; ns_sprintrr(&msg, &rr, NULL, NULL, dispbuf, sizeof(dispbuf)); puts(dispbuf); } }
想请教大家几个具体问题:
- 有没有办法强制
res_query使用我指定的DNS服务器? - 有没有
res_query相关的隐藏调试工具或未公开的文档,能看清它到底是怎么选择DNS服务器的? - 为什么抓包能看到正确的DNS响应,但
res_query却读不到,还返回「invalid argument」错误? - 有没有人遇到过macOS下
res_query和VPN的这种兼容性问题,有什么可行的解决思路?
内容来源于stack exchange
相关产品推荐
相关产品推荐

