sing-box的IPv4优先 IPv6优先行为受 gai.conf 控制?

前言

群友反馈在Deiban13下不能设置IPv4优先

通过进一步的交流, 群友的意思是 sing-box 向外访问, 无法通过 gai.conf 来设置是 IPv4优先 还是 IPv6优先
群友用的是fakeip的模式, 翻墙客户端发给梯子的数据包中只有域名, 没有IP.

技术基础




编译sing-box

准备测试环境

搭建一个简单的sing-box服务端
官方安装脚本 
curl -fsSL https://sing-box.app/install.sh | sh
配置文件
nano /etc/sing-box/test-config.json
{
  "log": {
    "level": "debug",
    "output": "test-box.log",
    "timestamp": true
  },
  "inbounds": [
    {
      "type": "socks",
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "listen_port": 1080
    }
  ],
  "outbounds": [
    {
      "type": "direct"
    }
  ]
}
命令行前台运行sing-box(不能Ctrl+C中断, 就这么放着)
/usr/bin/sing-box -D /var/lib/sing-box -c /etc/sing-box/test-config.json run
新开一个SSH终端窗口.
curl -x socks5h://127.0.0.1:1080 api.myip.la
curl的结果正常. 
查看sing-box的日志, 与 之前的测试记录一致
说明sing-box正常工作, DNS解析了域名. 


给 sing-box 挂钩子 指定使用系统 getaddrinfo

GODEBUG=netdns=cgo LD_PRELOAD=/root/hook_getaddrinfo.so /usr/bin/sing-box -D /var/lib/sing-box -c /etc/sing-box/test-config.json run
* 上面这是1整行

另一个SSH窗口用curl测试
curl -x socks5h://127.0.0.1:1080 api.myip.la
发现 sing-box 的窗口没有钩子的打印
检查 sing-box 的日志 也没有钩子的打印

分析 sing-box 的代码, 在哪里进行DNS解析

分析 sing-box 日志
INFO [548939013 0ms] inbound/socks[socks-in]: inbound connection from 127.0.0.1:38804
INFO [548939013 0ms] inbound/socks[socks-in]: inbound connection to api.myip.la:80
INFO [548939013 0ms] outbound/direct[0]: outbound connection to api.myip.la:80
DEBUG [548939013 0ms] dns: lookup domain api.myip.la
DEBUG [548939013 5ms] dns: exchanged api.myip.la NOERROR 595
DEBUG [548939013 5ms] dns: exchanged AAAA api.myip.la. 595 IN AAAA 2001:19f0:7001:5607:5400:1ff:fec7:13a9
DEBUG [548939013 5ms] dns: exchanged api.myip.la NOERROR 216
DEBUG [548939013 5ms] dns: exchanged A api.myip.la. 216 IN A 149.28.31.24
DEBUG [548939013 5ms] dns: lookup succeed for api.myip.la: 149.28.31.24 2001:19f0:7001:5607:5400:1ff:fec7:13a9
DEBUG [548939013 221ms] connection: connection upload finished
DEBUG [548939013 327ms] connection: connection download finished
找到关键词 lookup domain

我们打开sing-box源码
* 对, 就是把 sing-box项目的 github.com 改为 .dev 
** 当然, 我这是图省事的操作. 你愿意下载源码再用M$ VS打开也是一样的.

搜索 lookup domain
这就是sing-box打印日志的地方了.
https://github.dev/SagerNet/sing-box/blob/37608669865ef3b0df68cf076b58e451f56cdf3e/dns/router.go#L357

可以看到所在的这个 Lookup 函数里完成了DNS解析.

修改 sing-box 代码, 加入调用 getaddrinfo
我们加一行测试代码
为了编译通过, 文件头部要增加 imoprt "net"

把这个修改落实在 VPS
下载 sing-box 源码
修改 dns/router.go
在文件头部加入
import "net"
在 L359 行, 加入
net.LookupIP(domain)
* 不会用linux命令行修改, 或者觉得操作太麻烦, 你可以用Xftp修改文件

编译 sing-box
make
* 实际上是
export GOTOOLCHAIN=local && \
go build -v -trimpath -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=' -s -w -buildid=" -tags "with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale" ./cmd/sing-box

用新编译的sing-box进行测试
GODEBUG=netdns=cgo LD_PRELOAD=/root/hook_getaddrinfo.so /root/sing-box-1.12.12/sing-box run -D /var/lib/sing-box -c /etc/sing-box/test-config.json run
* 上面这是1整行

在另一个SSH窗口用curl socks5h进行测试
sing-box的窗口出现了熟悉的钩子打印日志

总结

当使用sing-box原始程序时, 指定使用系统getaddrinfo并挂钩子, 
日志没有钩子的打印记录

当sing-box代码中人为加入对getaddrinfo的调用后, 指定使用系统getaddrinfo并挂钩子,
日志有钩子的打印记录

说明sing-box原始程序 没有 使用系统getaddrinfo, 也就不受 gai.conf 控制.

评论

The Hot3 in Last 7 Days

搭 Docker版 Sub-Store 带 http-meta 实现 集合订阅 测延迟 排序 筛选 生成新订阅 定时任务上传Gist

极简一键脚本 搭NaiveProxy梯子 自定义端口 与Caddy V2前置的VLESS/Vmess V2Ray共存 可开CDN