如何在Alpine Linux 3.18中开启DNS TCP查询?
在Alpine Linux 3.18中开启DNS TCP查询的方法
Alpine Linux 3.18.0的发布说明提到musl 1.2.4支持基于TCP的DNS查询,但未说明开启方法。我尝试修改/etc/resolv.conf文件,在options中添加use-vc或tcp选项,配置如下:
第一种配置:
options timeout:2 attempts:3 rotate single-request-reopen use-vc ; generated by /usr/sbin/dhclient-script nameserver 100.100.2.136 nameserver 100.100.2.138
第二种配置:
options timeout:2 attempts:3 rotate single-request-reopen tcp ; generated by /usr/sbin/dhclient-script nameserver 100.100.2.136 nameserver 100.100.2.138
随后运行以下C程序测试:
#include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <stdlib.h> #include <netdb.h> #include <stdio.h> int main(int argc, char *argv[]) { struct addrinfo hints; struct addrinfo *result, *rp; int s; char host[256]; if (argc != 2){ printf("An argument must be specified, Usage:\n./%s <domainname or hostname>\n", argv[1]); exit(EXIT_FAILURE); } memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; s = getaddrinfo(argv[1], 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); }
运行结果:
./getaddrinfo-demo stackoverflow.com 151.101.1.69 151.101.65.69 151.101.129.69 151.101.193.69
同时在另一个窗口提前运行tcpdump命令抓包:
tcpdump -i eth0 -s 0 -nnv tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 20:09:26.732572 IP (tos 0x0, ttl 64, id 47125, offset 0, flags [DF], proto UDP (17), length 63) 172.17.0.3.46864 > 100.100.2.136.53: 53899+ A? stackoverflow.com. (35) 20:09:26.732604 IP (tos 0x0, ttl 64, id 16021, offset 0, flags [DF], proto UDP (17), length 63) 172.17.0.3.46864 > 100.100.2.138.53: 53899+ A? stackoverflow.com. (35) 20:09:26.732839 IP (tos 0x0, ttl 62, id 47125, offset 0, flags [DF], proto UDP (17), length 127) 100.100.2.136.53 > 172.17.0.3.46864: 53899 4/0/0 stackoverflow.com. A 151.101.1.69, stackoverflow.com. A 151.101.129.69, stackoverflow.com. A 151.101.65.69, stackoverflow.com. A 151.101.193.69 (99) 20:09:26.732841 IP (tos 0x0, ttl 62, id 16021, offset 0, flags [DF], proto UDP (17), length 127) 100.100.2.138.53 > 172.17.0.3.46864: 53899 4/0/0 stackoverflow.com. A 151.101.65.69, stackoverflow.com. A 151.101.193.69, stackoverflow.com. A 151.101.1.69, stackoverflow.com. A 151.101.129.69 (99)
抓包结果显示仍在使用UDP进行DNS查询,请问如何在Alpine Linux 3.18中正确开启DNS TCP查询?
解答
musl libc对resolv.conf的use-vc选项有特定逻辑,默认仅在UDP查询失败(如响应截断、超时)时才会切换到TCP。若要强制全程使用TCP查询,可按以下方式操作:
确保
resolv.conf配置不被覆盖- 部分环境中
dhclient-script会自动重写/etc/resolv.conf,执行cat /etc/resolv.conf确认use-vc选项存在且未被删除。 - 若使用NetworkManager等网络管理工具,需通过对应工具的配置文件添加DNS选项,避免被自动覆盖。
- 部分环境中
程序级强制TCP查询
在测试程序中手动开启强制TCP查询,需新增头文件并添加初始化代码:#include <resolv.h> // 新增头文件 // ... 原有代码 ... memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; // 强制启用TCP DNS查询 _res.options |= RES_USEVC; res_init(); // 重新初始化解析器配置 s = getaddrinfo(argv[1], NULL, &hints, &result); // ... 后续代码 ...系统级强制TCP查询
若要让所有程序默认使用TCP查询,在/etc/profile或/etc/environment中添加环境变量:export RES_OPTIONS="use-vc"执行
source /etc/profile使配置生效,之后所有依赖musl解析器的程序都会优先使用TCP进行DNS查询。验证生效状态
修改配置后重新运行测试程序并抓包,若观察到目标端口53的TCP连接(SYN、SYN-ACK、ACK数据包),则说明TCP查询已生效。
内容的提问来源于stack exchange,提问作者tdy218
相关产品推荐
相关产品推荐

