ChinaDNS-NG 1.0、2.0
为减少 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 在各自领域的优势,并有意避开彼此不擅长的领域。
dnsmasq还有一个功能是提供本地PTR查询,可以通过查询DHCP(v6)的租约文件实现
dnsmasq还有一个功能是提供本地PTR查询,可以通过查询DHCP(v6)的租约文件实现
这个功能涉及到 DHCP 领域,暂不考虑哈。
目前来说,我只想在合理的范围内,增加必要的功能。因此,完全取代 dnsmasq 并不是 chinadns-ng 的目的。
#119 有望进入2.0吗,感谢 不是催更,就问问
#119 有望进入2.0吗,感谢 不是催更,就问问
使用-d chn_A/gfw_A方案吗?(当然,具体方案还得 2.0 完成后 再定)
应该会考虑的,如果有时间的话,我只能说尽量哈。
记录下目前的进度和情况
大概有一个月的时间都花在了折腾zig的构建系统(build.zig)、开发环境、交叉编译等一系列问题。好在这些问题都解决的差不多了。
最近一周总算开始写zig逻辑代码了,zig写起来还是挺舒服的,确实解决了C语言的许多痛点。comptime特性很好用,比C++的模板/constexpr/consteval好太多了。
比如,我利用zig的comptime写了个printf格式字符串的检查例程,实现了类似gcc/clang对format参数的编译时检查功能。
希望此次zig之旅能够顺利,哈哈。
记录下目前的进度和情况
大概有一个月的时间都花在了折腾zig的构建系统(build.zig)、开发环境、交叉编译等一系列问题。好在这些问题都解决的差不多了。
最近一周总算开始写zig逻辑代码了,zig写起来还是挺舒服的,确实解决了C语言的许多痛点。comptime特性很好用,比C++的模板/constexpr/consteval好太多了。
比如,我利用zig的comptime写了个printf格式字符串的检查例程,实现了类似gcc/clang对format参数的编译时检查功能。
希望此次zig之旅能够顺利,哈哈。
牛的,我前段时间无聊。自己用golang写了一个功能类似的dns 工具,先用着 。期待chinadns2.0
这是我自己写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]中
第三点,你使用 remote-dns 来解析 vps 域名,是怕国内 dns 污染?
除此之外还有其他作用吗?
第三点,你使用 remote-dns 来解析 vps 域名,是怕国内 dns 污染?
除此之外还有其他作用吗?
就是怕污染,也是怕dns泄露之类的吧, 也是本地ssh访问vps服务器的时候不会走代理,不然会是好几个rtt
这是我自己写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的域名呢? 有两个可能
- 你的 vps 不是静态ip?
- 你用的 trojan/websocket类似的代理协议?
对于第一点, 可能没什么好办法咯.
对于第二点, 这些协议都可以 服务器填ip, 然后sni/servername的地方填域名, 这样代理客户端连接代理服务端就不需要解析你的域名 (我猜测这是你想解决的问题). 然后对于其他程序访问你的vps域名, 你可以把你的域名映射到 hosts里面去.
这是我自己写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的域名呢? 有两个可能
- 你的 vps 不是静态ip?
- 你用的 trojan/websocket类似的代理协议?
对于第一点, 可能没什么好办法咯.
对于第二点, 这些协议都可以 服务器填ip, 然后sni/servername的地方填域名, 这样
代理客户端连接代理服务端就不需要解析你的域名 (我猜测这是你想解决的问题). 然后对于其他程序访问你的vps域名, 你可以把你的域名映射到 hosts里面去.
手机什么的没有hosts 本质上我是既要ip的直连又要域名的国外解析,你想想这个
本质上来说,之所以不能简单的实现你的需求,是因为 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 功能搞定。
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
总结一下,可以通过新增 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 \
...
提一个疑问
如果配置文件里 没有指定 ipset 相关的配置 也就是国内 国外的 2个 txt 里的 只是区分了 转发的目标 并不会加入对应的ipset, 然后 上面说的这个其实和 txt 里写域名等效了 对吧?
提一个疑问
如果配置文件里 没有指定 ipset 相关的配置 也就是国内 国外的 2个 txt 里的 只是区分了 转发的目标 并不会加入对应的ipset, 然后 上面说的这个其实和 txt 里写域名等效了 对吧?
EDIT: 是的,具体见上面我的新评论,我举了更详细的几个例子,以及用途说明。
有没有打算做一个 广告域名的 配置呢? 如果有 我这边可以少一层套娃.
如果广告域名是类似 gfwlist.txt/chnlist.txt 这样的域名后缀,那么应该很简单。但是如果涉及到正则表达式等模式,那么不会考虑。
我不清楚通过 dns 过滤广告的效果如何,我觉得很多广告都是内嵌到网页里面的,仅在 域名解析 上动手,感觉不是非常理想。我很久之前也折腾过类似的基于 dns 的广告过滤(当然,并不是 AdGuardHome 哈),不过后来我还是用浏览器插件了。
如果广告域名是类似 gfwlist.txt/chnlist.txt 这样的域名后缀,那么应该很简单。但是如果涉及到正则表达式等模式,那么不会考虑。
我不清楚通过 dns 过滤广告的效果如何,我觉得很多广告都是内嵌到网页里面的,仅在 域名解析 上动手,感觉不是非常理想。我很久之前也折腾过类似的基于 dns 的广告过滤(当然,并不是 AdGuardHome 哈),不过后来我还是用浏览器插件了。
总之目前我还是插件. dns级别 需求其实不是非常高 多谢解答
有没有打算做一个 广告域名的 配置呢? 如果有 我这边可以少一层套娃.
Unix philosophy: Write programs that do one thing and do it well , 广告过滤交给其他专业软件吧, DNS 级别的广告过滤基本上没什么太大用处, 很多都无法过滤, 比如 youtube 广告, AdguardHome 都对此无能为力, 还得靠浏览器插件.
碰到 了一个见鬼的域名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 吧
可能部分用户还有另一个需求,就是腾讯的域名用腾讯的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不都得废?)
目前导致微信/京东某些界面转圈/打不开 基本上是阿里 dns (包括阿里的DoH DoT)造成的. 换成腾讯DNS或者114等其他的国内dns就不会有此问题.
还要能支持 kms的 _vlmcs._tcp 吧
这个我看了下,核心是让 chinadns-ng 支持创建 SRV 记录,响应相关查询。
目前来说不确定是否要支持,等 2.0 完成了再看看吧。
还是想重申下,chinadns-ng 2.0 虽然会考虑实现一些较为常用的功能,但目的不是替换 dnsmasq。
我仍然想让 chinadns-ng 保持简单和愚蠢,如果有些特殊需求无法满足,那我只能表示抱歉,希望大家理解。
只是看到写了2.0的目标是 替代传统的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合
所以最终还是要dnsmasq + chinadns-ng 2.0套娃,微信转圈只是举了一个例子,有的人可能和公司搞了穿透,公司域名要用公司的DNS解析。
嗯,确实描述不当,我做了修改:
之前:2.0 预计将使用单个 chinadns-ng 进程,替代传统的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合。
现在:2.0 预计将使用单个 chinadns-ng 进程,替代经典用例下的 dnsmasq + chinadns-ng + dns2tcp/dnsproxy 组合。
只是看到写了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 数据结构上进行了扩展,自定义组的匹配性能与内置组的一样,并且这些组都在同一个数据结构中)
2.0 的开发时间可能会比预计的长,因为我需要先用 Zig 将当前的大部分 chinadns-ng 功能重写掉,基本的功能/性能测试通过后,才会着手 2.0 的改造。因此 2.0 的目标仍然未最终确定,大家有什么想法也欢迎提出。
先把目前这个1.0的加入标准化的 tcp + udp 监听, tcp + udp 上游? 以及 udp 包过长会落到 tcp?