From 07376eb6904e4cae7458eebf487f6a37221eced6 Mon Sep 17 00:00:00 2001 From: Luna Yao <40349250+ZnqbuZ@users.noreply.github.com> Date: Tue, 17 Feb 2026 00:53:53 +0100 Subject: [PATCH] plan: add zone-wise acl control plan: fix config example --- easytier/src/dns/plan.md | 76 ++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/easytier/src/dns/plan.md b/easytier/src/dns/plan.md index b9e38761..18da96b7 100644 --- a/easytier/src/dns/plan.md +++ b/easytier/src/dns/plan.md @@ -1,15 +1,21 @@ -目标 ---- +## 目标 + 将 `instance/dns_server` 重写为单独的 `dns` 模块,为如下的配置项提供支持: + ```toml [dns] name = "localhost" # optional, replaces hostname, default to system hostname domain = "localdomain" # optional, replaces tld_dns_zone, default to et.net -[[dns.zone]] -broadcast = true # optional, propogate this config to all connected peers, default to false +# this policy applies to all zones with origin "example.com" +[dns."example.com".import] +whitelist = ["*"] +blacklist = [] +disabled = true # optional, whether to reject zones with this origin from connected peers, default to false +recursive = true # optional, apply this policy to all subzones, default to false -origin = "example.com" +[[dns.zone]] +origin = "example.com" # required, name of the zone ttl = 3600 # optional, default to 0 records = [ "www 60 IN A 123.123.123.123", @@ -20,7 +26,12 @@ forwarders = [ "1.1.1.1", ] # optional, forward DNS requests to these servers -# same zone, but not broadcasted +# this policy applies to the current zone block +[dns.zone.export] # if present, export this zone to connected peers +whitelist = ["*"] +blacklist = [] + +# same zone, but not exported [[dns.zone]] origin = "example.com" @@ -28,7 +39,9 @@ forwarders = [ "tcp://192.168.0.53:5353", ] ``` + 可能会支持的配置 + ```toml [dns] addresses = [ @@ -44,13 +57,13 @@ listeners = [ # these two options supersede accept_dns # setting both of them to empty is equivalent to set accept_dns = false, but zones are still broadcasted -``` +```

计划和进展

-protobuf ---- +## protobuf + - `ZoneConfigPb`:包含所有 Zone 配置,以及一个 ID,该 ID 在读取 TOML 时生成 - `DnsConfigPb`:包含 `name`、`domain` 和需要广播的 `ZoneConfigPb` - `DnsMessageId`: 标记 DnsClient 和它发送的 RPC 消息,避免乱序,包含:instance id, sequence number @@ -58,18 +71,19 @@ protobuf - `DnsPersistentConfig`: 用于 DnsServer 的长期接口,包含:id、listeners 和 addresses - `DnsHeartbeat`: DnsClient 发送的心跳,包含:id -DnsClient ---- +## DnsClient + 对于每个实例,它启动时读取 TOML 配置,然后用这个配置启动一个 DnsClient ,它需要做到: + 1. 启动时(配置更新时?)向 DnsServer 发送 listeners 和 addresses 2. 使用自己的 name 和 domain 创建一个专用 zone,让 name 指向自身 IP,并监听 IP 地址变化事件(为 DNS 一致性避免使用 127.0.0.1 作为 IP,若没有 IP 则不创建这个 zone) 3. 每次获得 PeerRouteInfo 时,读取其中的 dns 字段(和一些别的身份标记字段),这是个 protobuf message (DnsConfigPb),保存了远程 Peer 的 dns 配置(不含 addresses 和 listeners),接收后它需要: - 1. 用远程配置中的 name 和 domain 创建远程 peer 的专用 zone,让这个 name 指向 peer 的 ip(这些 ip 是在 PeerRouteInfo 中的) - 2. 检查 2., 3.i. 中得到的 zone、PeerRouteInfo 报告的 zone、本机 TOML 配置中的 zone 是否有变化,将所有有变化的 zone 报告给 DnsServer,如果没变化就不要上报 + 1. 用远程配置中的 name 和 domain 创建远程 peer 的专用 zone,让这个 name 指向 peer 的 ip(这些 ip 是在 PeerRouteInfo 中的) + 2. 检查 2., 3.i. 中得到的 zone、PeerRouteInfo 报告的 zone、本机 TOML 配置中的 zone 是否有变化,将所有有变化的 zone 报告给 DnsServer,如果没变化就不要上报 4. 每隔一小段时间向 DnsServer 发送心跳 -DnsServer ---- +## DnsServer + 每个 EasyTier 实例都会启动一个 DnsClient,但是一台机器上的所有实例共享一个唯一的 DnsServer。 每个实例启动时: @@ -80,15 +94,15 @@ DnsServer 需要做到: 1. 提供两个 RPC 接口,以及与之对应的配置清理机制: 1. 短期接口,该接口获得的配置更新频率较高,有效期与 DnsClient 的心跳间隔相同,比如:zone 2. 长期接口,该接口获得的配置更新频率较低,有效期与 DnsClient 的(配置)有效期相同,比如:listeners, addresses -2. 接受心跳时检查是否有死亡的 Zone,需要清除 -3. 持续检查是否有过期(丢失心跳)的 DnsClient,需要把这些 DnsClient 提供的 listeners, addresses 和 zone 清除 (应该不需要专门清理 zone) -4. 启动时自动添加 root zone,并把它的 forwarder 设置为系统 DNS -5. 使用短期接口更新 zone。不用合并同名 zone,直接用 Zone 结构体提供的 FallbackAuthority 按顺序插入 Catalog 就行,不过注意要先插入 InMemoryAuthority,这些都是 records,后插入 ForwardAuthority,这都是 forwarders -6. 更新 zone 的时候自动去掉 forwarder 中导致回环的那些,就是把 addresses 和 listeners 去掉(root zone 也需要这个逻辑) -7. 内部接口,控制 DnsServer 是否 bind 到某些 socket(也就是配置中的 listeners) -8. Listeners 绑定失败打印日志(失败一个打印一次然后就跳过),即便这时 addresses 为空也不要停机。(否则释放 socket 绑定后会有 instance 抢占 socket 试图启动 server,然后就死循环) -9. 内部接口,更新 addresses,并且给 tun 添加删除这些 addresses 的路由。目前这些用来 hijack 的 addresses 都是只支持 udp 简单查询,就是一个 UDP 包查询,tcp 完全不管。但是可以支持除了 53 之外的端口,这个不难。 -10. 启动时,往 packet pipeline 上挂一个 filter,和目前 magic dns 的操作一样,给 addresses 添加路由并劫持所有目的为配置中 addresses 的 UDP 包,直接作为 DNS request 读取并交给 DnsServer 解析(这个 addresses 可能还得 append 到 resolv.conf 之类的地方) +2. 接受心跳时检查是否有死亡的 Zone,需要清除 +3. 持续检查是否有过期(丢失心跳)的 DnsClient,需要把这些 DnsClient 提供的 listeners, addresses 和 zone 清除 (应该不需要专门清理 zone) +4. 启动时自动添加 root zone,并把它的 forwarder 设置为系统 DNS +5. 使用短期接口更新 zone。不用合并同名 zone,直接用 Zone 结构体提供的 FallbackAuthority 按顺序插入 Catalog 就行,不过注意要先插入 InMemoryAuthority,这些都是 records,后插入 ForwardAuthority,这都是 forwarders +6. 更新 zone 的时候自动去掉 forwarder 中导致回环的那些,就是把 addresses 和 listeners 去掉(root zone 也需要这个逻辑) +7. 内部接口,控制 DnsServer 是否 bind 到某些 socket(也就是配置中的 listeners) +8. Listeners 绑定失败打印日志(失败一个打印一次然后就跳过),即便这时 addresses 为空也不要停机。(否则释放 socket 绑定后会有 instance 抢占 socket 试图启动 server,然后就死循环) +9. 内部接口,更新 addresses,并且给 tun 添加删除这些 addresses 的路由。目前这些用来 hijack 的 addresses 都是只支持 udp 简单查询,就是一个 UDP 包查询,tcp 完全不管。但是可以支持除了 53 之外的端口,这个不难。 +10. 启动时,往 packet pipeline 上挂一个 filter,和目前 magic dns 的操作一样,给 addresses 添加路由并劫持所有目的为配置中 addresses 的 UDP 包,直接作为 DNS request 读取并交给 DnsServer 解析(这个 addresses 可能还得 append 到 resolv.conf 之类的地方) 11. Addresses 和 Listeners 更新时需要检查所有 zone 的 forwarder,之前为了避免回环可能去掉了一些 forwarder,或者有新的 forwarder 要去除 此外,还有以下几个设计要点: @@ -98,16 +112,16 @@ DnsServer 需要做到: 另外任何关于系统 DNS 的操作,清理都参考现有的 magic dns。 -问题 ---- +## 问题 + - [ ] [minor] the ttl option isn't working because of https://github.com/hickory-dns/hickory-dns/pull/3450 - [minor] address 路由绑定必须在有 tun 的实例上做;listener 绑定则与 tun 无关,现有竞选机制无法保证有 tun 的实例能优先启动 DnsServer - - 或许让 DnsClient 控制关于 address 的路由和 filter,并通过 RPC 转发 DNS 请求?有两个问题:DnsServer 必须得知 addresses 否则无法进行环路检测;多个 DnsClient 同时修改 resolv.conf 添加自己得 address 容易出问题 - - 或许不妨假设大多数情况下一台机器上所有实例的 no_tun 设置相同,这时候这个问题实际上不存在 + - 或许让 DnsClient 控制关于 address 的路由和 filter,并通过 RPC 转发 DNS 请求?有两个问题:DnsServer 必须得知 addresses 否则无法进行环路检测;多个 DnsClient 同时修改 resolv.conf 添加自己得 address 容易出问题 + - 或许不妨假设大多数情况下一台机器上所有实例的 no_tun 设置相同,这时候这个问题实际上不存在 - [minor] DnsServer 更新 zone 的时候需要更精细的合并/去重控制 -TODO ---- +## TODO + - [x] 配置解析 - [ ] 用 OSPF 传播需要广播的配置 - [ ] 用 DNS RPC 更新收到的配置,合并相同的域,延迟低的 peer 配置优先 @@ -128,7 +142,9 @@ TODO - related to https://github.com/EasyTier/EasyTier/issues/1645 - related to https://github.com/EasyTier/EasyTier/issues/1764 - related to https://github.com/EasyTier/EasyTier/issues/1814 + --- + - (maybe) related to https://github.com/EasyTier/EasyTier/issues/937 - (maybe) related to https://github.com/EasyTier/EasyTier/issues/1873