V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LEXUGE
V2EX  ›  DNS

dcompass - 纯 Rust 实现的高性能混合 DNS 服务器

  •  
  •   LEXUGE · 2020-11-18 10:03:20 +08:00 via iPhone · 9552 次点击
    这是一个创建于 1469 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://github.com/LEXUGE/dcompass

    具体内容都在 GitHub 里,功能大概为: 高速( 760 qps ) 自由路由规则,支持递归嵌套,且提供完整运行前功能检查 支持 DoH (未来支持 UDP ) 缓存持久化,应对恶劣网络环境 应对网络环境热切换(不会出现 SmartDNS Wi-Fi 换 4G 直接 DoH 断连的问题) IPv6 AAAA 屏蔽 选择性 SNI 发送,防止 SNI 被侦测 纯 Rust 实现 轻量域名匹配( 160 us per match )

    目前自用体验良好,deploy it and forget it 自测速度快于 smartdns ( 640 qps )

    nixos 用户可以看一下 https://github.com/icebox-nix/netkit.nix ,内含打包好的 dcompass 以及可以直接使用的 nixos module

    第 1 条附言  ·  2020-11-18 12:16:20 +08:00
    qps 是真实网络环境下多次测试结果,不是 mock test
    第 2 条附言  ·  2020-11-20 11:36:56 +08:00
    目前提供 windows, linux, linux-armv7, macos 的 binary
    https://github.com/LEXUGE/dcompass/actions/runs/373581534
    欢迎下载测试
    69 条回复    2020-12-26 14:35:32 +08:00
    billzhuang
        1
    billzhuang  
       2020-11-18 11:15:49 +08:00 via iPhone
    支持下,阅读代码中
    no1xsyzy
        2
    no1xsyzy  
       2020-11-18 11:17:06 +08:00
    建议发 /go/create
    lbp0200
        3
    lbp0200  
       2020-11-18 11:34:29 +08:00
    异步模型用的协程吗?
    LEXUGE
        4
    LEXUGE  
    OP
       2020-11-18 12:15:52 +08:00
    @lbp0200 (不是很了解具体术语)是基于 tokio runtime 的,目前因为 tokio 0.2 和 0.3 的迁移,upstream 是 single-threaded 的,event loop 是 multi-threaded. 未来迁移以后可能性能会更好一些
    xarthur
        5
    xarthur  
       2020-11-18 12:19:58 +08:00
    支持 ipset 吗?
    tpsxiong
        6
    tpsxiong  
       2020-11-18 12:36:16 +08:00 via Android
    支持 unbound 那样的迭代查询不
    LEXUGE
        7
    LEXUGE  
    OP
       2020-11-18 13:05:56 +08:00 via iPhone
    @xarthur 目前还不支持,但是代码设计的时候就考虑到这点了
    LEXUGE
        8
    LEXUGE  
    OP
       2020-11-18 13:06:58 +08:00 via iPhone
    @tpsxiong recursive query 吗,只要请求写了 recursive needed 的话上游就会支持,因为实际上这是一个 DNS 转发服务器
    shynome
        9
    shynome  
       2020-11-18 13:13:03 +08:00 via Android
    qps 要讲在什么配置下的,不同配置下的 qps 不同
    LEXUGE
        10
    LEXUGE  
    OP
       2020-11-18 13:17:57 +08:00 via iPhone   ❤️ 1
    @shynome 我给两个测试用了相同语义的配置。虽然数据会有变化,但是还是能反应在相同网络环境和相同设备上的速度的。
    Jirajine
        11
    Jirajine  
       2020-11-18 13:28:14 +08:00 via Android
    不错,正好也想用 rust 实现一个 dns 转发器。
    提几个建议:
    1. 配置文件支持 yaml/toml 。
    2. 把核心逻辑抽出来写成 lib,方便调用。
    3. 支持更多规则,正则、abp 等。
    4. 支持扩展插件,弄个 Python 脚本或者像 coredns 一样留个框架让用户自己添加代码再重编译。
    Jirajine
        12
    Jirajine  
       2020-11-18 13:31:10 +08:00 via Android
    以及 smartdns 特有的 过期缓存、prefetch 、速度测试等,这样就可以完全替代,解决 smartdns 仅 Linux 可用的问题。
    LEXUGE
        13
    LEXUGE  
    OP
       2020-11-18 13:43:57 +08:00 via iPhone
    @Jirajine 插件还未考虑,不过核心逻辑 droute 是一个 lib,且提供 trait 支持自己实现匹配规则
    Jirajine
        14
    Jirajine  
       2020-11-18 13:53:54 +08:00 via Android
    @LEXUGE 我这里指的插件主要是 hook,让用户在处理请求时注入自己的自定义代码。
    大概是这样:
    fn process_dns(&c: Context){
    plugin_A(c);
    plugin_B(c);
    // 用户自己实现一个函数或类型,然后插入到这里。
    }
    然后在你自己的核心逻辑中调用 process_dns 函数。
    tpsxiong
        15
    tpsxiong  
       2020-11-18 14:52:11 +08:00
    @LEXUGE iterative dns query
    zro
        16
    zro  
       2020-11-18 15:22:43 +08:00
    能不能像 dnsmasq 那样可以有 add-subnet 选项,配合上游 EDNS 。。

    好像没找到其他能 add-subnet 的 DNS 转发,包括 unbound~~
    LEXUGE
        17
    LEXUGE  
    OP
       2020-11-18 21:40:54 +08:00 via iPhone
    @zro 目前只做了包转发,added to the todo list
    INTEL2333
        18
    INTEL2333  
       2020-11-18 23:53:32 +08:00 via Android
    话说大佬,能不能做个双栈 EDNS
    v4 和 v6 非同一个运营商提供的时候非常难受

    比如 A 记录走 8888,AAAA 记录走 2001:4860:4860::8888

    或者

    向 8.8.8.8 发送两次查询,EDNS 分别对应 v4 和 v6
    zro
        19
    zro  
       2020-11-19 00:41:47 +08:00
    @INTEL2333 #18 应该跟你差不多,v6 是 HE 的,能说下你是什么方案吗?
    我现在的方案不太成熟,要开两个 unbound,其中一个只查 v6 。。。
    INTEL2333
        20
    INTEL2333  
       2020-11-19 08:13:30 +08:00 via Android
    @zro 我现在是开了 2 个 adgh

    adgh1 是 v4 only

    adgh2 是选优模式,上游 adgh1 和 2001:4860:4860::8888

    不过出结果太慢了
    LEXUGE
        21
    LEXUGE  
    OP
       2020-11-19 08:16:05 +08:00
    @zro EDNS 我没有
    @INTEL2333 可以考虑,不过我没有 v6 环境,很难测试
    LEXUGE
        22
    LEXUGE  
    OP
       2020-11-19 08:17:13 +08:00
    新加入了 DNS over TLS 功能的支持
    INTEL2333
        23
    INTEL2333  
       2020-11-19 08:18:29 +08:00 via Android
    @zro 还有个可能不符合你要求的解决方案,只用一个 adgh

    用 8.8.8.8 并过滤
    240e:*
    2408:*
    2409:*
    INTEL2333
        24
    INTEL2333  
       2020-11-19 08:21:48 +08:00 via Android
    @LEXUGE 唔,应该不用 v6 环境也能测试,方案 2 的话,应该指定一下 edns 地址就可以了

    蟹蟹大佬啦
    HalloCQ
        25
    HalloCQ  
       2020-11-19 08:46:52 +08:00
    @zro 支持 edns 的大把。overture,adguardhome 等等
    LEXUGE
        26
    LEXUGE  
    OP
       2020-11-19 08:51:27 +08:00
    @HalloCQ overture 挺 buggy 的...我还修过一个 bug...也就是因为它和 smartdns 都很 buggy 我才决定自己写
    打算支持 EDNS,回去写个 roadmap
    HalloCQ
        27
    HalloCQ  
       2020-11-19 08:52:54 +08:00
    @LEXUGE 我也没用它了,刚换成 adgh,感觉挺好用
    zgzh
        28
    zgzh  
       2020-11-19 13:44:34 +08:00
    感谢~已经部署,成功运行,查询速度很快
    zro
        29
    zro  
       2020-11-19 13:47:36 +08:00
    @INTEL2333 #23
    ADGH 要是能加上“只查询 IPv6”功能就好弄多了;像你这样 ADGH 开一个 v4 only 的,有遇到像这样的情况吗?
    手机挂 Surge 开 T 宝,查最近请求时发现,居然还会访问某个 v6 IP 的网站,无域名的;偶尔一打开又会问我要不要切换到美国版 T 宝。。但看 Surge 的请求,IP 归属地都是五星旗

    @HalloCQ #25

    ADGH 的 ECS settings:edns_client_subnet — Enable EDNS Client Subnet option. If enabled, AdGuard Home will be sending ECS extension to the upstream DNS servers. Please note, that this will be done for clients with public IP addresses only.

    从公网查询才有效果的。。因为我是在境外 VPS 搭,所以需要像 dnsmasq 的 add-subnet 这样的功能,没发现 ADGH 有其他 ECS 的设置~
    INTEL2333
        30
    INTEL2333  
       2020-11-19 14:28:45 +08:00 via Android
    @zro 唔,没遇到过
    上面那个方案其实还可以节省一个 adgh

    上游 8.8.8.8 和 2001:4860:4860::64,选优模式

    过滤
    240e:*
    2408:*
    2409:*
    64:ff9b::*

    不过似乎会造成无 aaaa 的域名在查询 aaaa 记录时返回时间超过 1s
    INTEL2333
        31
    INTEL2333  
       2020-11-19 14:30:49 +08:00 via Android
    @zro 话说淘宝会不会也有类似腾讯的 httpdns ?
    如果有的话似乎就难办了,只能 ip6tables 来 drop 了
    LEXUGE
        32
    LEXUGE  
    OP
       2020-11-19 16:42:09 +08:00 via iPhone
    @zgzh 啊这,我都没法 crate,你直接 build 的吗
    我不敢保证现在不会有 breaking change,不过感谢支持
    zgzh
        33
    zgzh  
       2020-11-19 16:57:36 +08:00
    @LEXUGE 是的 下载源码后 cargo build --release,在树莓派上顺利构建
    LEXUGE
        34
    LEXUGE  
    OP
       2020-11-19 18:02:36 +08:00 via iPhone
    @zgzh 那我打算提供一下交叉编译版本
    HalloCQ
        35
    HalloCQ  
       2020-11-20 09:25:33 +08:00
    @zro 因为你的 adgh 部署在服务器上,当你本地向 adgh 请求的时候,adgh 拿到的就是你的公网 ip 了
    HalloCQ
        36
    HalloCQ  
       2020-11-20 09:27:51 +08:00
    @zro 就算运营商分配给你的不是公网 ip,但是你 adgh 是搭在一个外网的 vps 上,难道 adgh 还能拿到你的内网 ip 不成?
    zro
        37
    zro  
       2020-11-20 13:07:48 +08:00
    @HalloCQ #35 Sorry,没说清楚,本地是以 VPN 跟外网 VPS 连的,所以 ADGH 根本不知道我的外网 IP 。。ADGH 没有对外暴露端口的~
    HalloCQ
        38
    HalloCQ  
       2020-11-20 16:58:33 +08:00
    @zro 我是把 adgh 部署到国内服务器,然后分流。国内域名用 doh.pub ,国外域名请求 dns.google 。速度快的不行,还能去广告
    2001225354
        39
    2001225354  
       2020-11-21 17:33:34 +08:00
    会有路由器版本么
    LEXUGE
        40
    LEXUGE  
    OP
       2020-11-21 18:56:01 +08:00
    LEXUGE
        41
    LEXUGE  
    OP
       2020-11-21 19:02:42 +08:00
    目前支持的架构有 x86_64-unknown-linux-musl, armv7-unknown-linux-musleabihf, armv5te-unknown-linux-musleabi, x86_64-pc-windows-gnu, x86_64-apple-darwin, aarch64-unknown-linux-musl 。
    已经测试的设备有:windows, linux, raspberry pi 3B+ (openwrt,使用 aarch64 ),都可以直接下载运行
    可能有问题的架构:apple-darwin (不知道为什么, GitHub Action 的 Catalina 编译出来 linker 会炸)
    未来可能会支持: mips
    大部分的架构都使用了 musl 静态编译,尽可能无依赖,欢迎测试
    有新的架构想加入 release 编译的 list 可以留言
    fengjianxinghun
        42
    fengjianxinghun  
       2020-11-21 20:00:44 +08:00
    我也有个类似的。。。
    静态插件是这样
    pub static GLOBAL_MODULE_TABLES:Lazy<Mutex<Vec<Box<dyn Fn() -> Box<dyn PFilter<Output=PAction> + Send> + Send>>>> = Lazy::new(|| .....

    然后在 async/await hook 点生成新的 trait PFilter 对象
    fengjianxinghun
        43
    fengjianxinghun  
       2020-11-21 20:10:36 +08:00
    还有,既然是 rust 。按照传统,建议支持 toml 配置。
    ysc3839
        44
    ysc3839  
       2020-11-21 20:13:18 +08:00 via Android
    请问目前有实现 overture 的功能吗?
    希望实现先查询 A DNS,如果返回的 IP 数据匹配某个列表再去查询 B DNS,并返回 B DNS 的结果。
    目前似乎只有 overture 能实现这样的逻辑。
    LEXUGE
        45
    LEXUGE  
    OP
       2020-11-21 21:46:03 +08:00
    @fengjianxinghun 求链接? toml 考虑支持
    @ysc3839 后期打算加入复杂服务端的配置(如 DoH 服务端),以及更加自由的路由配置(有点搞得像 table 了),这样可以部署在自己的服务器上
    LEXUGE
        46
    LEXUGE  
    OP
       2020-11-21 21:48:25 +08:00
    @ysc3839 这么做其实有 blacklist 的意思,但是 IP blacklist 很难维护且感觉过滤效果不好。目前 dcompass 只支持 prequery 的 routing.
    ysc3839
        47
    ysc3839  
       2020-11-21 21:54:47 +08:00 via Android
    @LEXUGE 这里的 list 是中国的 IP 地址,感觉是比较好维护的。主要是为了解决 CDN 的问题。
    LEXUGE
        48
    LEXUGE  
    OP
       2020-11-22 15:37:28 +08:00
    @ysc3839 加入 todo list
    LEXUGE
        49
    LEXUGE  
    OP
       2020-11-30 11:34:24 +08:00
    新增加了 mock test,忽略掉网络因素下 qps 为 100000 。
    实际测试(网络环境好时):2500 qps
    在网络环境差且请求量大时,增加了可选的 ratelimit (使用 token bucket 实现)

    下一步将设计一个简单灵活的路由规则语法
    JBaker
        50
    JBaker  
       2020-12-03 11:24:56 +08:00
    请问有中文的说明文件吗?
    实在不想再看英文的帮助了(躺)
    JBaker
        51
    JBaker  
       2020-12-03 11:43:34 +08:00
    问一下,chche_size 的单位是什么呢?条目?字节? MB ?
    ==============
    我觉得还能接着加功能
    - 比如对 纯 ipv6 用户 还有 教育网用户(ipv6 免流的) 添加“如果有 ipv6 地址,则只返回 ipv6 地址”的控制项(例如可以叫做 ipv6_only 或者 disable_ipv4)
    - 比如自定义 DNS 解析结果的 hosts
    - 比如,如果没有加配置文件进来,就弹出界面,傻瓜式地生成配置文件 (能偷懒为何要费劲写 json 呢?还容易打错字。)
    - 比如,指定日志文件和缓存文件的保存位置(我想存到内存盘里)
    - 比如,添加“以服务方式安装和自启动”(脚本可以抄 dnscrypt 的 service_install.bat)

    暂时就想到这么多。折腾是永不停止的。折腾完,程序运行就慢下来了 ohhhhhhh
    JBaker
        52
    JBaker  
       2020-12-03 11:49:08 +08:00
    上一行是 cache_size,又打错字了。
    还有,如果我的 upstream 填的是 根服务器的 IP,能正确的处理请求吗?
    还有,我想同时监听 127.0.0.1:53 和 [::1]:53,该怎么填?花括号"address":{"127.0.0.1:53","[::1]:53"}还是 "address": ["127.0.0.1:53","[::1]:53"],亦或者是"address": "127.0.0.1:53","address": "[::1]:53",写两行?
    JBaker
        53
    JBaker  
       2020-12-03 13:38:56 +08:00
    Error: 远程主机强迫关闭了一个现有的连接。 (os error 10054)
    issues/2
    我就随便打开一个网站就这样了。
    LEXUGE
        54
    LEXUGE  
    OP
       2020-12-03 15:58:49 +08:00
    @JBaker 前两个都可以通过未来的路有规则实现。
    生成配置可能没有,不过如果不喜欢 json 未来可以支持 TOML 。
    缓存文件持久化意义不大,DNS 结果很容易过期的...日志可以考虑
    服务的话 linux 下我写了 systemd service unit,windows 我不太会,欢迎 PR
    cache_size 的单位是 per record.
    LEXUGE
        55
    LEXUGE  
    OP
       2020-12-04 08:28:42 +08:00
    @JBaker 已修复(
    原因是某些应用会发多个请求,却在第一个请求收到后就走掉了,导致 socket 挂了(
    LEXUGE
        56
    LEXUGE  
    OP
       2020-12-05 16:15:23 +08:00
    已实现自由组合路由规则
    不过目前还没有增加 ipcidr 和 geoip 的 matcher,暂时没办法实现 IP 分流,但是逻辑上已经实现了
    LEXUGE
        57
    LEXUGE  
    OP
       2020-12-08 10:59:29 +08:00   ❤️ 1
    @ysc3839
    目前新增加了 GeoIP matcher (自带数据库),可以轻松实现 clash 的防污染逻辑
    ```yaml
    table:
    - tag: start
    if: any
    then:
    - query: domestic
    - check_secure
    - tag: check_secure
    if:
    geoip:
    - CN
    else:
    - query: secure
    - end
    ```
    ylx
        58
    ylx  
       2020-12-14 17:52:17 +08:00
    能不能给个通用用户的配置
    开箱即用的
    zgzh
        59
    zgzh  
       2020-12-17 15:37:41 +08:00
    @LEXUGE 最新版本"disable_ipv6": true, 无效,还是可以解析出 IPV6,是不是取消了?
    LEXUGE
        60
    LEXUGE  
    OP
       2020-12-17 22:09:14 +08:00
    @zgzh 是的,为了灵活适应需求,我把所有的这些选项做成了路由插件,可以自由组合,如果要禁用 IPv6 可以使用 Qtype(AAAA) 来匹配并使用 disable 来设置禁用,具体见 https://gist.github.com/LEXUGE/f629c9229851c5ad5816469de2495eca

    目前配置变动可能比较频繁,未来可能会加入多个 inbounds 的选项,也会有 breaking change,不过我会不 break

    如果有使用方面的问题,可以发 https://github.com/LEXUGE/dcompass/discussions,回复比较及时
    LEXUGE
        61
    LEXUGE  
    OP
       2020-12-17 22:19:36 +08:00   ❤️ 1
    @ylx 如果你说的通用是指简单的防污染分流的话,可以: https://gist.github.com/LEXUGE/17f5c4a9d77e5fbe2b2a7fe1bd85fb1f

    无需任何外置的文件(域名列表,IP 列表之类的)

    @zgzh 上面一条发的也有点小错误,还是以 repo 下的 configs 为准,那些是会过 CI tests 的。
    zgzh
        62
    zgzh  
       2020-12-17 22:33:33 +08:00
    @LEXUGE 路由器。。。空间着急。。那个附加文件太大了,,txt 的还可以放得下。。
    zgzh
        63
    zgzh  
       2020-12-17 22:42:07 +08:00
    @LEXUGE 哇。。。原来还可以不用附件了参数了,很赞,谢谢
    LEXUGE
        64
    LEXUGE  
    OP
       2020-12-17 23:07:17 +08:00
    @zgzh 我考虑编译一组不内置 maxmind geoip 数据库的 binary,但是得明天了。

    另外有中文 README (中文写的不太顺手) https://github.com/LEXUGE/dcompass/blob/main/README-CN.md
    ylx
        65
    ylx  
       2020-12-18 11:22:22 +08:00
    上面提到了 host IP 功能
    你说通过路由功能实现 能不能给个例子
    比如怎么写让 baidu.com 解析到 127.0.0.1 谢谢
    ylx
        66
    ylx  
       2020-12-18 11:23:21 +08:00
    LEXUGE
        67
    LEXUGE  
    OP
       2020-12-18 13:58:12 +08:00
    @ylx 正在做,预计会有 min (不自带 database), mid (自带 GeoIP2-CN), 和 full (自带 maxminddb) 三种版本。


    @ylx 目前还没有对任意域名自定义结果的 Action,如果你单纯是想要 block 所有 baidu 的网址的话,可以用 domain matcher + disable action 来实现。自定义结果的话本质是一个 upstream,我在考虑怎么设计可以让语法更简洁

    PS: 建议在 GitHub repo 的 Discussion page 上提问,v2ex 我不一定会看
    LEXUGE
        68
    LEXUGE  
    OP
       2020-12-18 23:09:43 +08:00
    @ylx
    @zgzh

    https://github.com/LEXUGE/dcompass/releases/tag/build-20201218_2249
    三种不同的构建已经完成了,单纯防污染建议选择 `cn`, 开箱即用且空间占用仅仅比 `min` 大 500 KB.
    LEXUGE
        69
    LEXUGE  
    OP
       2020-12-26 14:35:32 +08:00
    支持 IP CIDR matching
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5723 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:46 · PVG 10:46 · LAX 18:46 · JFK 21:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.