Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ChinaDNS-NG 2.0 #144

Closed
15 of 16 tasks
zfl9 opened this issue Nov 12, 2023 · 62 comments
Closed
15 of 16 tasks

ChinaDNS-NG 2.0 #144

zfl9 opened this issue Nov 12, 2023 · 62 comments

Comments

@zfl9
Copy link
Owner

zfl9 commented Nov 12, 2023

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


1.0 版本要实现的功能 (已完成,见 2024.03.07 版本):

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

2.0 版本要实现的功能:

  • 支持 DNS 缓存,支持缓存白名单(不被缓存的域名),支持 stale 缓存模式。
  • 缓存 tag:none 域名的判定结果,减少不必要的转发/判定,减少 DNS 泄露。
  • 支持读取 hosts 文件(本地 A/AAAA 记录),支持定义本地 A/AAAA 记录。
  • 考虑支持 DNS over HTTPS 上游(可选的,不带 DoH 的可能称为 lite 版)
  • --cache-stale 参数最大值调整,目前最大是 65535(u16),某些情况下不太够
  • 允许过滤具有某些 qtype 的查询消息,如 qtype=64/65,用于某些特殊需求 #82
  • 必要的 dnsmasq 类似功能(--server--ipset定义其他类型的 DNS 记录
  • tcp:// 上游增加 pipeline 长连接支持,目前是采用的是 tcp 短连接 #151
  • 支持 DNS over TLS 上游(会发布两种版本,不需要此功能的请选 lite 版)
  • add ip to ipset/nftset 时,允许指定 element 级别的 timeout 参数 #155
  • 支持定义其他类型的本地 DNS 记录,如 SRV (有需求请单独开 issue)

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

@InspoOnU
Copy link

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

@zfl9
Copy link
Owner Author

zfl9 commented Nov 18, 2023

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

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


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

@Smallthing

This comment was marked as off-topic.

@zfl9

This comment was marked as off-topic.

@zfl9

This comment was marked as outdated.

@xtccc

This comment was marked as resolved.

@xtccc

This comment was marked as resolved.

@zfl9

This comment was marked as resolved.

@xtccc

This comment was marked as resolved.

@cattyhouse

This comment was marked as resolved.

@xtccc

This comment was marked as resolved.

@zfl9

This comment was marked as outdated.

@zfl9

This comment was marked as outdated.

@zfl9

This comment was marked as outdated.

@kuyagic

This comment was marked as outdated.

@zfl9

This comment was marked as outdated.

@kuyagic
Copy link

kuyagic commented Dec 29, 2023

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

@zfl9
Copy link
Owner Author

zfl9 commented Dec 29, 2023

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

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

@kuyagic
Copy link

kuyagic commented Jan 5, 2024

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

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

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

@cattyhouse
Copy link

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

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

@muziling
Copy link

muziling commented Jan 12, 2024

碰到 了一个见鬼的域名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 吧

@zfl9
Copy link
Owner Author

zfl9 commented Jan 15, 2024

可能部分用户还有另一个需求,就是腾讯的域名用腾讯的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不都得废?)

@cattyhouse
Copy link

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

@zfl9
Copy link
Owner Author

zfl9 commented Jan 15, 2024

还要能支持 kms的 _vlmcs._tcp 吧

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

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

@zfl9
Copy link
Owner Author

zfl9 commented Jan 15, 2024

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

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

@muziling
Copy link

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

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

@InspoOnU

This comment was marked as resolved.

@mm11253

This comment was marked as resolved.

@zfl9

This comment was marked as resolved.

@mm11253

This comment was marked as resolved.

@zfl9
Copy link
Owner Author

zfl9 commented Mar 6, 2024

更新下进度,1.0版本已基本完成,测试了几天,暂未发现问题。

快的话这几天会更新master分支、README、发布1.0的release版本。

见 2024.03.07 版本。

@muziling
Copy link

想了下,好像和dnsmasq套娃是必须的, 所以实不实现dnsmasq的功能好像都没关系, 路由器需要dnsmasq来提供DHCP服务。
最终方案都是 dnsmasq + chinadns-ng

@zfl9
Copy link
Owner Author

zfl9 commented Mar 11, 2024

想了下,好像和dnsmasq套娃是必须的, 所以实不实现dnsmasq的功能好像都没关系, 路由器需要dnsmasq来提供DHCP服务。 最终方案都是 dnsmasq + chinadns-ng

路由器上,你说的是有道理的(但不绝对)

实际上你可以关闭 dnsmasq 的 DNS 功能,只用 DHCP。
因为 dnsmasq 的 TCP DNS 实现效率很低,会 fork 很多 dnsmasq 进程出来。

不是所有人都在(主)路由器上使用,所以实现某些常用/必要功能仍然有意义。

@xtccc
Copy link

xtccc commented Mar 11, 2024

想了下,好像和dnsmasq套娃是必须的, 所以实不实现dnsmasq的功能好像都没关系, 路由器需要dnsmasq来提供DHCP服务。
最终方案都是 dnsmasq + chinadns-ng

也不一定吧,我现在使用systemd-networkd 的dhcp server,用着也还可以

@22ccy
Copy link

22ccy commented Mar 12, 2024

Make chinadns-ng great again!

@zfl9 zfl9 changed the title ChinaDNS-NG 1.0、2.0 ChinaDNS-NG 2.0 Mar 15, 2024
@zfl9
Copy link
Owner Author

zfl9 commented Mar 25, 2024

见最新 2024.03.25 版本,新增了以下功能:

  • DNS 缓存、缓存忽略、缓存预刷新等。
  • tag:none 域名的判定结果缓存。

2024.03.27 版本,新增了以下功能:

  • 支持读取 hosts 文件
  • 支持定义本地 A/AAAA 记录

剩下的 TODO 要稍微等一段时间,先忙些其他事情了。

@zfl9
Copy link
Owner Author

zfl9 commented Mar 29, 2024

计划有变,由于 DoH 最低推荐 HTTP/2,纯手撸一个 HTTP/2 客户端不现实,看了其他实现,要么是使用语言(标准库)自带的 http 库,要么是使用第三方库(如 libcurl);C/Zig 没有自带的 http 库。

也看了一些有关 DoH 和 DoT 的讨论,最终决定使用 DoT,相比较 DoH,少了一层 http 协议,可以减少协议开销。

想了下,浏览器更“喜欢” DoH 是因为浏览器本身就有完备的 HTTPS 客户端支持,而其他更底层的实现(如 systemd-resolved)则更偏好于 DoT,虽然不知道具体原因,但肯定有很大一部分是 HTTP/2 协议带来的复杂度导致的。

关于 DoH 和 DoT 的争论,主要是这一点:

  • DoH 使用 443 端口,可藏匿于常规 HTTPS 流量中
  • DoT 使用 853 端口,相比较 HTTPS/443,更容易被识别

不过我想说的是,真想找出哪些是 DoH 流量,哪些是 HTTPS 流量,太简单了,直接 ip 识别即可(dst_ip=公共DNS && dst_port=443),所以这个观点站不住脚;更何况 DoH 流量的数据包大小明显不同于常规网站 HTTPS 的数据包大小。

也就是说,国内DNS“藏不住”,国外DNS没必要藏(反正都走了代理)。

@zfl9

This comment was marked as resolved.

@zfl9
Copy link
Owner Author

zfl9 commented Apr 13, 2024

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

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

已实现,使用自定义组即可,自由搭配 upstream、ipset/nftset。

@xtccc

@ir1ka
Copy link

ir1ka commented Apr 14, 2024

请问有计划在 gfwlist.ext 和 ignlist.ext 中实现正则表达式做分流支持吗?

@zfl9
Copy link
Owner Author

zfl9 commented Apr 14, 2024

没有这个计划。

什么需求会要用到正则?

@ir1ka
Copy link

ir1ka commented Apr 14, 2024

我看到一些能找到的 gfwlist 文件是用 AutoProxy 写的,里面很多会用到正则表达式,如果做转换为 chinadns-ng 支持的格式比较麻烦。

还有就是请问下对 chinadns-ng 里面对 子域名的子域名 是怎么处理的?
比如我在 gfwlist.ext 中写了 xxxx.com,它能匹配 a.xxxx.com,它是否能匹配 b.a.xxxx.com

@zfl9
Copy link
Owner Author

zfl9 commented Apr 15, 2024

我看到一些能找到的 gfwlist 文件是用 AutoProxy 写的,里面很多会用到正则表达式,如果做转换为 chinadns-ng 支持的格式比较麻烦。

这个大可不必担心,有很多成熟的 gfwlist2dnsmasq 工具,也有很多现成的 gfwlist.txt 域名列表。它们会处理正则表达式(一般也就是 google.*blogspot.*,都是可以简单枚举出来的)。


chinadns-ng 的 dnl(domain name list,域名列表),里面配置的是 “域名后缀”。模式 xxx.com 可以匹配:

  • xxx.com
  • a.xxx.com
  • b.a.xxx.com
  • c.b.a.xxx.com
  • 以此类推

@zfl9
Copy link
Owner Author

zfl9 commented Apr 27, 2024

2.0 已完成,见最新 2024.04.27 版本。其他问题请单独开 issue 讨论。

@zfl9 zfl9 closed this as completed Apr 27, 2024
@Karmylr
Copy link

Karmylr commented Jun 30, 2024

记录下目前的进度和情况

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

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

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

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

能不能说下zig解决了c的哪些痛点

@zfl9
Copy link
Owner Author

zfl9 commented Jul 1, 2024

能不能说下zig解决了c的哪些痛点

C 的定位其实是“可移植的汇编语言”,因此 C 不可能有太多语言方面的更改(看看 C11、C17、C23 就明白了)。

作为 C 程序员,我一直在寻找另一门“更现代”的 C 语言,它具有与 C 一样的简单性(显然 C++、Rust 并不“简单”)、高性能(带 GC 的语言首先被排除,比如 Go),因此我找到了 Zig。

正如官网以及很多博客所说,Zig 致力于打造一门更现代的 C 语言。但就目前来看,Zig 还不足以完全替代 C,长远来看,也不可能取代 C,与 C/C++ 共存应该是一个比较理想的情况。而且 Zig 目前的热度一般,距离 Zig 1.0 也还有许多工作要做,我相信多数人都是因为 zig cc/c++ 编译工具链 接触的 Zig,我也不例外。

下面来说说 Zig 解决了什么问题(都是我个人的实际使用体验):

  • 更严格的编译时检查、运行时检查(Debug/Safe构建模式),能避免不少低级错误,对问题排查也更友好。
  • 指针类型细分:单对象指针、多对象指针(长度未知)、切片(多对象指针+长度)、哨兵终止的多对象指针/切片。
  • 数组是值类型,不会像 C 那样自动退化为指针。
  • 有原生的向量类型(SIMD),虽然我目前还没用过。
  • 好用的 comptime,比 C++ 模板那套优雅的多,条件编译、泛型都是常规 Zig 语法,不再是晦涩的模板语言。
  • 比 C 更丰富的标准库,不过目前还不够成熟和稳定,我目前仍然使用 C 库为主,仅使用 Zig 的数据结构/算法。
  • 自带构建系统(zig build),构建系统是用 Zig 描述的,而不是其他语言(Shell、Makefile、CMakeLists.txt)。
  • 自带完善的交叉编译工具链,自带 C、C++ 编译器,自带 musl 源码库,这是 Zig 可以与 C/C++ 无缝集成的基础。
  • 可以直接导入 C 头文件(原理是将头文件中的 C 源码翻译为 Zig 源码,并且可以识别大部分的宏),而不是依赖 FFI。
  • 没有默认初始化(如初始化为 0),所有初始化都是显式的。
  • optional 类型、optional 指针。
  • 错误处理比较优雅,尤其是对比 C、Go。
  • 没有隐式的控制流,代码容易阅读,比如标准库的可读性就很不错(因为缺少文档,我直接都是看源码)。
  • 任意位宽的整数类型(i1 ~ i65535u1 ~ u65535
  • 和 lua “一切皆 table”一样,Zig 也可以笼统的说“一切皆 struct”,因为 Zig 源文件也是一个 struct。
  • 枚举字面量(Enum Literals)很好用,可以省略 Enum 类型前缀,清爽,舒服。
  • 块级别的 defer,可以很大程度取代 C 中 Goto 的使用场景(退出时进行“清理”操作)。
  • 一切皆表达式,可以给块(block)打 label,这样块就可以有“返回值”了(有点类似立即运行的匿名函数)。
  • 异步语法糖(这是我打算用 Zig 重写 ChinaDNS-NG 的最根本原因),但目前异步在自托管编译器中尚未回归。

不足之处,或者说让我感到不爽的地方:

  • 缺少 C printf 风格的可变参数,虽然 Zig 有 anytype 参数 + struct/tuple literal 可以实现“编译时”的可变参函数,但这本质上是一种“泛型”,会导致代码膨胀,这也是为什么我没有使用 Zig 的 fmt/print/log API,而是继续使用 C 的 printf + 基于 comptime 的 fmt 字符串的编译时检查。
  • 没有 C 宏,我知道宏经常被妖魔化,但宏并不是什么洪水猛兽,合理使用仍然是有益的,而且 inline fn + comptime 并不能完全替代 C 宏的所有用例,宏对于减少重复代码/片段仍然是一个好工具。另外,宏对于某些写法的条件编译也很非常有用,比如结构体字段的条件编译。
  • 缺少 goto,同上,goto 也被妖魔化,但合理使用仍然是有益的;其中一个用例是错误处理,虽然 defer/errdefer 可以解决大部分用例,但有时仍然不够,好在可以使用 labeled block 进行弥补,所以这方面基本可以忽略;但 goto 还有一个重要用途,那就是 computed goto,这对于编写高性能的语言解释器/VM 是非常有益的(用于 dispatch table 热循环)。
  • 缺少分支级别的 likely/unlikely 提示,目前只有一个函数级别的 @setCold()
  • 没有块注释(如 /* xxx */),只有行注释,不是什么很严重问题,但有些情况下块注释确实更合适。
  • 参数传递存在一个“隐式魔法”:复合类型的参数是由编译器来决定到底是“值传递”还是“引用传递”的,如 fn foo(obj: SomeStruct) void 中的 obj;如果结构中存在自引用指针,可能就会出问题(当编译器选择值传递时);当然还有其他问题,zig issue 中有讨论。我觉得这种就应该明确“值传递”,就像 C/C++ 那样,如果要引用传递,那就声明为指针类型。
  • 没有 函数返回类型 自动推导,有时候写 comptime 函数时,需要单独写一个函数来计算返回类型,比较麻烦。
  • 没有 C 风格的 for 循环,没有 do while,不是什么严重问题,但有时候确实需要它们。
  • 缺少对结构体布局的细微控制(只有 packed struct),缺少位域(对于定义网络协议很有用,特别是 DNS)。
  • 静态变量的地址不是 comptime known 的,静态初始化空链表时(自引用结构)比较蛋疼,只能在运行时初始化。
  • 编译时反射需要进一步完善,如 @Type() 不支持带 decls(声明),导致某些条件编译的写法比较蹩脚。
  • 赋值表达式没有返回值,不能像 C 那样搞 if (foo(...) && (x = bar(...)) && (y = baz(...)) 等操作,只能 if 嵌套。
  • @sizeOf() 只能接受类型参数,要是能像 C 那样接受任意表达式就好了,这样就可以减少对 @TypeOf() 的使用了。
  • 结果位置语义需要进一步完善,要是可以使用 @result() 拿到“结果位置”的指针就好了,可以进行更多控制。
  • 命名 shadowing 过于严格,导致变量起名比较困难,虽然能理解这样做的原因,但还是带来不少的麻烦。
  • 异步仍然未回归,希望 Zig 开发团队能多分配一些精力在这方面。

更新:

  • 关于 async,我脑海中已经有思路了,可以手动模拟实现。(必须借助编译器)
  • 位域可以通过 packed struct(T) 实现,并且比 C 的位域更好,因为位顺序是确定的。
  • 结构体布局这块,比如要描述 DNS 协议,使用 extern struct + packed struct 即可。
  • computed goto 已经有相关 issue:introduce labeled continue syntax inside a switch expression ziglang/zig#8220

@Karmylr
Copy link

Karmylr commented Jul 6, 2024

@zfl9 comptime比constexpr和consteval好在哪呢

@zfl9
Copy link
Owner Author

zfl9 commented Jul 6, 2024

comptime 基本等于 C++ template + consteval + constexpr,而且 comptime 是常规 zig 语法。

另外,zig 有编译时的反射:@Type()@typeInfo(),这在 C++ 里面是没有的。

@lwintermelon
Copy link

@zfl9

缺少对结构体布局的细微控制(只有 packed struct),缺少位域(对于定义网络协议很有用,特别是 DNS)。

这个讨论你有注意到吗,期待有更好的解决方案和命名。

@zfl9
Copy link
Owner Author

zfl9 commented Aug 13, 2024

是的,我赞同了这个评论。zig 确实需要更强大的类型建模能力。虽然现在勉强能满足,但略微繁琐。

zig 中的 packed struct 与 C 的 packed struct(如 GCC/Clang 的 __attribute__((packed)))不是一回事,我花了一些时间才搞懂,我怀疑这个命名误导了很多人。

zig 的 packed struct 实际上是一种 特殊的整数,只是这个整数的内存布局用一个结构体来描述。结构体各字段的类型只能是整数类型(bool、enum 也是整数的一种),packed struct 中的字段,按照其声明顺序,依次从“底层整数”中分配 bit(从底层整数的 LSB 最低有效位 开始分配,一直到 MSB 最高有效位)。这些 bit 字段之间不存在填充/间隙。

所以我非常赞同将 packed struct 改为 bitfield struct。

C 的 struct { ... } __attribute__((packed)) 实际上是一种语法糖,给结构体的每个成员设置 align(1) 属性,因为 C 结构体本身具有确定性的内存布局(位域除外),再加上 align(1) 强制按 1 字节对齐,就得到了“紧凑 struct”。zig 目前也可以做到这一点,使用 extern struct,然后手动给每个 field 附上 align(1) 属性。但这有点繁琐,我希望有一种快捷方式,比如类似 C,在 struct 上设置 align(1),我记得看到过类似提案、issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests