You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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查询,可按以下方式操作:

  1. 确保resolv.conf配置不被覆盖

    • 部分环境中dhclient-script会自动重写/etc/resolv.conf,执行cat /etc/resolv.conf确认use-vc选项存在且未被删除。
    • 若使用NetworkManager等网络管理工具,需通过对应工具的配置文件添加DNS选项,避免被自动覆盖。
  2. 程序级强制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);
    // ... 后续代码 ...
    
  3. 系统级强制TCP查询
    若要让所有程序默认使用TCP查询,在/etc/profile或/etc/environment中添加环境变量:

    export RES_OPTIONS="use-vc"
    

    执行source /etc/profile使配置生效,之后所有依赖musl解析器的程序都会优先使用TCP进行DNS查询。

  4. 验证生效状态
    修改配置后重新运行测试程序并抓包,若观察到目标端口53的TCP连接(SYN、SYN-ACK、ACK数据包),则说明TCP查询已生效。


内容的提问来源于stack exchange,提问作者tdy218

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:40:02