chinadns-ng icon indicating copy to clipboard operation
chinadns-ng copied to clipboard

ChinaDNS-NG 1.0、2.0

Open zfl9 opened this issue 2 years ago • 44 comments

为减少 DNS 工具链的“套娃”,提高 chinadns-ng 的易用性,我计划开发 1.0、2.0 版本。


1.0 版本要实现的功能:

  • [x] 支持 TCP + UDP 监听,尽量符合相关 RFC 规范
  • [x] 支持多个监听 IP 地址,方便 IPv4 + IPv6 双栈等用例
  • [x] 支持 TCP + UDP 上游,处理方式类似 dnsmasq,但可能会有所增强(如:强制 TCP 上游~~或 UDP 上游~~)
  • [x] 每个上游组允许配置多个 DNS(超过 2 个),允许混用多个不同协议的 DNS 上游(TCP、UDP)
  • [x] 引入配置文件支持,语法类似 dnsmasq,一行一个长选项

2.0 版本要实现的功能:

  • [ ] 支持 DNS 缓存,缓存策略类似于 dnsmasq 的 --use-stale-cache
  • [ ] 在可能的范围内,考虑支持 DNS over HTTPS (DoH),注意,目前不会考虑支持 HTTP/3(QUIC)
  • [ ] DoH 支持(依赖 OpenSSL)是可选的,根据实际需求选择 lite/full 版本
  • [ ] 其他 必要的、常用的 dnsmasq 类似功能

预计将使用单个 chinadns-ng 进程,替代经典用例下的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合。


1.0/2.0 将使用 Zig + C 混合开发,混合开发是为了最大程度发挥 Zig 和 C 在各自领域的优势,并有意避开彼此不擅长的领域。

zfl9 avatar Nov 12 '23 22:11 zfl9

dnsmasq还有一个功能是提供本地PTR查询,可以通过查询DHCP(v6)的租约文件实现

InspoOnU avatar Nov 18 '23 07:11 InspoOnU

dnsmasq还有一个功能是提供本地PTR查询,可以通过查询DHCP(v6)的租约文件实现

这个功能涉及到 DHCP 领域,暂不考虑哈。


目前来说,我只想在合理的范围内,增加必要的功能。因此,完全取代 dnsmasq 并不是 chinadns-ng 的目的。

zfl9 avatar Nov 18 '23 08:11 zfl9

#119 有望进入2.0吗,感谢 不是催更,就问问

Smallthing avatar Dec 02 '23 15:12 Smallthing

#119 有望进入2.0吗,感谢 不是催更,就问问

使用-d chn_A/gfw_A方案吗?(当然,具体方案还得 2.0 完成后 再定)

应该会考虑的,如果有时间的话,我只能说尽量哈。

zfl9 avatar Dec 02 '23 15:12 zfl9

记录下目前的进度和情况

大概有一个月的时间都花在了折腾zig的构建系统(build.zig)、开发环境、交叉编译等一系列问题。好在这些问题都解决的差不多了。

最近一周总算开始写zig逻辑代码了,zig写起来还是挺舒服的,确实解决了C语言的许多痛点。comptime特性很好用,比C++的模板/constexpr/consteval好太多了。

比如,我利用zig的comptime写了个printf格式字符串的检查例程,实现了类似gcc/clang对format参数的编译时检查功能。

希望此次zig之旅能够顺利,哈哈。

zfl9 avatar Dec 20 '23 14:12 zfl9

记录下目前的进度和情况

大概有一个月的时间都花在了折腾zig的构建系统(build.zig)、开发环境、交叉编译等一系列问题。好在这些问题都解决的差不多了。

最近一周总算开始写zig逻辑代码了,zig写起来还是挺舒服的,确实解决了C语言的许多痛点。comptime特性很好用,比C++的模板/constexpr/consteval好太多了。

比如,我利用zig的comptime写了个printf格式字符串的检查例程,实现了类似gcc/clang对format参数的编译时检查功能。

希望此次zig之旅能够顺利,哈哈。

牛的,我前段时间无聊。自己用golang写了一个功能类似的dns 工具,先用着 。期待chinadns2.0

xtccc avatar Dec 21 '23 16:12 xtccc

这是我自己写dns时候的一点想法,作者看看有没有价值 我的ss-tproxy用的chnroute 模式 前两个是照抄chinadns-ng的,第三个是我根据自己的需求思考的

  • [x] 白名单内的域名: dns 解析使用223.5.5.5 , 直接访问ip
  • [x] 黑名单内的域名: dns 解析使用1.1.1.1 , 使用代理访问ip
  • [x] 对于vps的域名处理: dns 解析使用 1.1.1.1 , 使用直连访问ip 域名在黑名单里 新建立一个文件vps_doamins.ext 记录vps的域名,如果dns 查询域名是vps域名,则不将其ip加入sstp_black[6]中,而是将其ip地址添加到sstp_white[6]中

xtccc avatar Dec 25 '23 09:12 xtccc

第三点,你使用 remote-dns 来解析 vps 域名,是怕国内 dns 污染?

除此之外还有其他作用吗?

zfl9 avatar Dec 25 '23 09:12 zfl9

第三点,你使用 remote-dns 来解析 vps 域名,是怕国内 dns 污染?

除此之外还有其他作用吗?

就是怕污染,也是怕dns泄露之类的吧, 也是本地ssh访问vps服务器的时候不会走代理,不然会是好几个rtt

xtccc avatar Dec 25 '23 10:12 xtccc

这是我自己写dns时候的一点想法,作者看看有没有价值 我的ss-tproxy用的chnroute 模式 前两个是照抄chinadns-ng的,第三个是我根据自己的需求思考的

  • [x] 白名单内的域名: dns 解析使用223.5.5.5 , 直接访问ip
  • [x] 黑名单内的域名: dns 解析使用1.1.1.1 , 使用代理访问ip
  • [x] 对于vps的域名处理: dns 解析使用 1.1.1.1 , 使用直连访问ip 域名在黑名单里 新建立一个文件vps_doamins.ext 记录vps的域名,如果dns 查询域名是vps域名,则不将其ip加入sstp_black[6]中,而是将其ip地址添加到sstp_white[6]中

为什么要解析VPS的域名呢? 有两个可能

  1. 你的 vps 不是静态ip?
  2. 你用的 trojan/websocket类似的代理协议?

对于第一点, 可能没什么好办法咯.

对于第二点, 这些协议都可以 服务器填ip, 然后sni/servername的地方填域名, 这样代理客户端连接代理服务端就不需要解析你的域名 (我猜测这是你想解决的问题). 然后对于其他程序访问你的vps域名, 你可以把你的域名映射到 hosts里面去.

cattyhouse avatar Dec 25 '23 10:12 cattyhouse

这是我自己写dns时候的一点想法,作者看看有没有价值 我的ss-tproxy用的chnroute 模式 前两个是照抄chinadns-ng的,第三个是我根据自己的需求思考的

  • [x] 白名单内的域名: dns 解析使用223.5.5.5 , 直接访问ip
  • [x] 黑名单内的域名: dns 解析使用1.1.1.1 , 使用代理访问ip
  • [x] 对于vps的域名处理: dns 解析使用 1.1.1.1 , 使用直连访问ip 域名在黑名单里 新建立一个文件vps_doamins.ext 记录vps的域名,如果dns 查询域名是vps域名,则不将其ip加入sstp_black[6]中,而是将其ip地址添加到sstp_white[6]中

为什么要解析VPS的域名呢? 有两个可能

  1. 你的 vps 不是静态ip?
  2. 你用的 trojan/websocket类似的代理协议?

对于第一点, 可能没什么好办法咯.

对于第二点, 这些协议都可以 服务器填ip, 然后sni/servername的地方填域名, 这样代理客户端连接代理服务端就不需要解析你的域名 (我猜测这是你想解决的问题). 然后对于其他程序访问你的vps域名, 你可以把你的域名映射到 hosts里面去.

手机什么的没有hosts 本质上我是既要ip的直连又要域名的国外解析,你想想这个

xtccc avatar Dec 25 '23 10:12 xtccc

本质上来说,之所以不能简单的实现你的需求,是因为 tag:gfw 和 tag:chn 承担了两个角色:

  • 转发给特定上游dns
  • 将域名解析结果加入ipset/nftset

如果我们将这两个功能拆分开,那么问题就迎刃而解。也即,将它们分别对应两个域名列表txt:

  • forward-to-upstream.txt:用于查询时的转发判定
  • add-ip-to-set.txt:用于响应时的添加ip至set

考虑到绝大多数 tag:chn、tag:gfw 域名都需要执行上述两种功能(也即转发判定,结果ip添加至set),为了方便(也主要是考虑到程序效率,以及兼容老的chinadns-ng),可以给 chinadns-ng 新增一个选项,比如:

--special-domains <file>,文件格式类似 ini,比如这样:

[forward.china]
xxx.com
...

[forward.trust]
yyy.com
...

[add.chnip]
aaa.com
...

[add.gfwip]
bbb.com
...

预计这个文件不会很大,最多十几个域名,因为绝大部分域名都可以使用原有的 --gfwlist-file/--chnlist-file 功能搞定。

zfl9 avatar Dec 25 '23 11:12 zfl9

chinadns-ng 2.0 准备加入配置文件支持,因为目前选项有点多了,使用配置文件会好一点,起码看起来清爽许多。

也许另一个选择是不添加上述说的 --special-domains <file> 选项,而是添加几个更简单的选项来搞定,因为这种特殊需求的域名数量不多,似乎没必要单独划分一个文件出来。

chinadns.conf 配置文件,语法很简单,一行一个(长)选项,空行和井号开头的行被忽略

# 监听地址和端口
bind-addr 127.0.0.1
bind-port 65353

# china上游,可以重复指定,也支持传统的逗号隔开
china-dns 223.5.5.5
china-dns 119.29.29.29

# trust上游,同上
trust-dns 8.8.8.8
trust-dns 1.1.1.1

# 域名列表文件,因为文件很大,所以用单独txt存储
chnlist-file /path/to/chnlist.txt
gfwlist-file /path/to/gfwlist.txt

# ipset相关
add-tagchn-ip
add-taggfw-ip gfwip,gfwip6
ipset-name4 chnroute
ipset-name6 chnroute6

# 特殊域名(也就上面讨论的)
#
# 转发给china上游的
forward-china xxx.com
forwrad-china xyz.com
#
# 转发给trust上游的
forward-trust abc.com
forward-trust foo.com
#
# 添加到chnip集合的(add-tagchn-ip)
add-chnip bar.com
add-chnip baz.com
#
# 添加到gfwip集合的(add-taggfw-ip)
add-gfwip yyy.com
add-gfwip ppp.com

# 其他选项...
verbose

zfl9 avatar Dec 25 '23 11:12 zfl9

总结一下,可以通过新增 4 个更细分的 命令行选项/配置 来满足这种特别的需求:

注意,这可能不是最终实现方案,具体请看此 issue 的最新评论。

  • --forward-china 域名:等价于 --chnlist-file 中的域名,但仅限于 forward 上下文。
  • --forward-trust 域名:等价于 --gfwlist-file 中的域名,但仅限于 forward 上下文。
  • --add-chnip 域名:等价于 --chnlist-file 中的域名,但仅限于 add-ip 上下文。
  • --add-gfwip 域名:等价于 --gfwlist-file 中的域名,但仅限于 add-ip 上下文。

注意,如果未启用 --add-tagchn-ip [set4,set6],则 --add-chnip <domain> 没有实际效果;同理,如果未启用 --add-taggfw-ip <set4,set6>--add-gfwip <domain> 没有实际效果。(当然,如果能从头来过,将 命令行选项 重新规划/细分下,其实就不会有这个限制了。不过考虑到现状以及现实需求,目前这个小限制应该无伤大雅)。


比如,在启用了 --add-tagchn-ip、--add-taggfw-ip 的情况下,以下配置是完全等价的:

# chnlist.txt
baidu.com

# gfwlist.txt
google.com

# 命令行
chinadns-ng -m chnlist.txt -g gfwlist.txt ...
# 命令行
chinadns-ng --forward-china baidu.com --add-chnip baidu.com \
            --forward-trust google.com --add-gfwip google.com ...

如果未启用 --add-tagchn-ip、--add-taggfw-ip,那么上述两个配置也是等价的,因为此时 --add-chnip、--add-gfwip 没有效果。

这里说它们是等价的,是从宏观上看的,实际上你不应该在这种情况下使用 --forward-*--add-*ip,因为它们不适合大量配置,否则你会遇到与 dnsmasq --server/--ipset 类似的性能问题。


只有在这两种情况下,你才需要上述提出的几个新选项:

  • 某个域名,在 forward 时需要转发给 china 上游,但 add-ip 时需要添加到 gfw-ipset
  • 某个域名,在 forward 时需要转发给 trust 上游,但 add-ip 时需要添加到 chn-ipset

这里用命令行选项举个例子:

# chnlist.txt 的域名,forward 给 china 上游,add-ip 到 chn-ipset
# gfwlist.txt 的域名,forward 给 trust 上游,add-ip 到 gfw-ipset
# foo.com 这个域名后缀,forward 给 china 上游,add-ip 到 gfw-ipset
# bar.com 这个域名后缀,forward 给 trust 上游,add-ip 到 chn-ipset
# 其他域名(tag:none),forward 给 china 和 trust 上游,使用 chnroute/chnroute6 进行 ip 判定
chinadns-ng \
    -m chnlist.txt \
    -g gfwlist.txt \
    --add-tagchn-ip chnip,chnip6 \
    --add-taggfw-ip gfwip,gfwip6 \
    --ipset-name4 chnroute \
    --ipset-name6 chnroute6 \
    --forward-china foo.com \
    --forward-trust bar.com \
    --add-chnip bar.com \
    --add-gfwip foo.com \
    ...

zfl9 avatar Dec 25 '23 11:12 zfl9

提一个疑问

如果配置文件里 没有指定 ipset 相关的配置 也就是国内 国外的 2个 txt 里的 只是区分了 转发的目标 并不会加入对应的ipset, 然后 上面说的这个其实和 txt 里写域名等效了 对吧?

kuyagic avatar Dec 29 '23 06:12 kuyagic

提一个疑问

如果配置文件里 没有指定 ipset 相关的配置 也就是国内 国外的 2个 txt 里的 只是区分了 转发的目标 并不会加入对应的ipset, 然后 上面说的这个其实和 txt 里写域名等效了 对吧?

EDIT: 是的,具体见上面我的新评论,我举了更详细的几个例子,以及用途说明。

zfl9 avatar Dec 29 '23 06:12 zfl9

有没有打算做一个 广告域名的 配置呢? 如果有 我这边可以少一层套娃.

kuyagic avatar Dec 29 '23 08:12 kuyagic

如果广告域名是类似 gfwlist.txt/chnlist.txt 这样的域名后缀,那么应该很简单。但是如果涉及到正则表达式等模式,那么不会考虑。

我不清楚通过 dns 过滤广告的效果如何,我觉得很多广告都是内嵌到网页里面的,仅在 域名解析 上动手,感觉不是非常理想。我很久之前也折腾过类似的基于 dns 的广告过滤(当然,并不是 AdGuardHome 哈),不过后来我还是用浏览器插件了。

zfl9 avatar Dec 29 '23 08:12 zfl9

如果广告域名是类似 gfwlist.txt/chnlist.txt 这样的域名后缀,那么应该很简单。但是如果涉及到正则表达式等模式,那么不会考虑。

我不清楚通过 dns 过滤广告的效果如何,我觉得很多广告都是内嵌到网页里面的,仅在 域名解析 上动手,感觉不是非常理想。我很久之前也折腾过类似的基于 dns 的广告过滤(当然,并不是 AdGuardHome 哈),不过后来我还是用浏览器插件了。

总之目前我还是插件. dns级别 需求其实不是非常高 多谢解答

kuyagic avatar Jan 05 '24 14:01 kuyagic

有没有打算做一个 广告域名的 配置呢? 如果有 我这边可以少一层套娃.

Unix philosophy: Write programs that do one thing and do it well , 广告过滤交给其他专业软件吧, DNS 级别的广告过滤基本上没什么太大用处, 很多都无法过滤, 比如 youtube 广告, AdguardHome 都对此无能为力, 还得靠浏览器插件.

cattyhouse avatar Jan 06 '24 01:01 cattyhouse

碰到 了一个见鬼的域名s5.m3u8.cool,dig显示huaweicloud,只能附加部分国家的ecs才能解析出地址,比如cloudcone就解析不到IP,oracle韩国可以, oracle美国好像不行。 类似这种:https://ping.chinaz.com/r2.hfyrw.com ,内地可以,外网反而有部分解析不到

chinadns-ng 2.0 会有这功能吗? 目前只有mosdns能满足需求

可能部分用户还有另一个需求,就是腾讯的域名用腾讯的DNS解析,解决微信转圈的问题

如果替代dnsmasq,还要能支持 kms的 _vlmcs._tcp 吧

muziling avatar Jan 12 '24 13:01 muziling

可能部分用户还有另一个需求,就是腾讯的域名用腾讯的DNS解析,解决微信转圈的问题

你直接使用腾讯的 119.29.29.29 作为 china 上游组,应该就可以了吧?

~~如果你的意思是让 chinadns-ng 能够为 特定域名 使用单独的 dns 上游,如 腾讯域名列表(tencent.txt) 使用 腾讯DNS上游(119.29.29.29),那可能永远不会支持,因为 chinadns-ng 的核心就是两组 DNS 上游(china + trust),如果要进行这种更改,则将违反核心设计。~~

更新:2024.04.13 版本起,使用自定义组即可满足类似需求。公司域名走公司DNS、腾讯域名走腾讯DNS。

另外,我似乎没有遇到过你说的微信转圈问题(也许是部分地区?或者特殊网络环境?),如果这种情况很普遍,那岂不是说腾讯/微信相关的域名必须使用腾讯自己的DNS?(我认为不大可能,否则除了腾讯DNS外的其他公共DNS不都得废?)

zfl9 avatar Jan 15 '24 07:01 zfl9

目前导致微信/京东某些界面转圈/打不开 基本上是阿里 dns (包括阿里的DoH DoT)造成的. 换成腾讯DNS或者114等其他的国内dns就不会有此问题.

cattyhouse avatar Jan 15 '24 07:01 cattyhouse

还要能支持 kms的 _vlmcs._tcp 吧

这个我看了下,核心是让 chinadns-ng 支持创建 SRV 记录,响应相关查询。

目前来说不确定是否要支持,等 2.0 完成了再看看吧。

zfl9 avatar Jan 15 '24 07:01 zfl9

还是想重申下,chinadns-ng 2.0 虽然会考虑实现一些较为常用的功能,但目的不是替换 dnsmasq。

我仍然想让 chinadns-ng 保持简单和愚蠢,如果有些特殊需求无法满足,那我只能表示抱歉,希望大家理解。

zfl9 avatar Jan 15 '24 07:01 zfl9

只是看到写了2.0的目标是 替代传统的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合

所以最终还是要dnsmasq + chinadns-ng 2.0套娃,微信转圈只是举了一个例子,有的人可能和公司搞了穿透,公司域名要用公司的DNS解析。

muziling avatar Jan 15 '24 08:01 muziling

嗯,确实描述不当,我做了修改:

之前:2.0 预计将使用单个 chinadns-ng 进程,替代传统的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合。

现在:2.0 预计将使用单个 chinadns-ng 进程,替代经典用例下的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合。

zfl9 avatar Jan 15 '24 08:01 zfl9

只是看到写了2.0的目标是 替代传统的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合

所以最终还是要dnsmasq + chinadns-ng 2.0套娃,微信转圈只是举了一个例子,有的人可能和公司搞了穿透,公司域名要用公司的DNS解析。

我思考了下,在设计上确实可以再优化下,考虑到之前提出的几个新选项:

--forward-china 域名:等价于 --chnlist-file 中的域名,但仅限于 forward 上下文。 --forward-trust 域名:等价于 --gfwlist-file 中的域名,但仅限于 forward 上下文。 --add-chnip 域名:等价于 --chnlist-file 中的域名,但仅限于 add-ip 上下文。 --add-gfwip 域名:等价于 --gfwlist-file 中的域名,但仅限于 add-ip 上下文。

我认为可以这样,让 chinadns-ng 支持部分 dnsmasq 功能(比如 --server、--ipset、--nftset),满足你们说的这些特殊需求,这样就不必增加之前提到的 --forward-*、--add-*ip 选项了,并且会让 chinadns-ng 更灵活,容易扩展。

chinadns-ng 只针对 chnlist/gfwlist.txt 进行性能优化(也就是现在做的这样),因为此类域名很多,优化是非常值得且必要的;

而对于其他 dnsmasq 的功能,~~则进行常规实现(类似 dnsmasq),因为这些肯定不存在大量域名,没必要花时间做深度优化~~。(已经在原有的 dnl.c 数据结构上进行了扩展,自定义组的匹配性能与内置组的一样,并且这些组都在同一个数据结构中)

zfl9 avatar Jan 15 '24 09:01 zfl9

2.0 的开发时间可能会比预计的长,因为我需要先用 Zig 将当前的大部分 chinadns-ng 功能重写掉,基本的功能/性能测试通过后,才会着手 2.0 的改造。因此 2.0 的目标仍然未最终确定,大家有什么想法也欢迎提出。

zfl9 avatar Jan 15 '24 09:01 zfl9

先把目前这个1.0的加入标准化的 tcp + udp 监听, tcp + udp 上游? 以及 udp 包过长会落到 tcp?

cattyhouse avatar Jan 15 '24 09:01 cattyhouse