Files
vps/docs/lan-dns-architecture.md
T

14 KiB

内网 DNS 架构调研与优化建议

状态:2026-08-12 调研定稿,Linear W1N-56Phase 0 验证(2026-08-12)全部完成,最终裁决(用户定稿)已对齐;本期未改动任何生产 DNS 路径。 2026-08-12 现场核查修正:gfw 上 mosdns 不是闲置——它是 OpenClash clash 的 nameserver/default-nameserver(DIRECT 规则真实 IP 解析),处于活动链路,裁决第 5 条 的"删除闲置 mosdns"前提不成立,处置改为"正式纳管并文档化"。 相关:docs/lan-overview.mdhosts/dns.windy.lan.mdhosts/gfw.windy.lan.md、W1N-40。

1. 现状(实测 2026-08-12)

角色 部署 职责 是否在活动路径
AdGuard Home 192.168.66.36(PVE VM 120,Docker host 网络) EdgeRouter DHCP 通告给 LAN55/66 客户端的唯一 DNS;广告/过滤、查询统计、Web 面板 是(LAN 客户端唯一入口)
mosdns 192.168.66.1(gfw OpenWrt)监听 127.0.0.1:6052(仅本机) clash 的 nameserver/default-nameserver:DIRECT 规则真实 IP 分流(国内 → AGH .36:53,国外 → 223.5.5.5/119.29.29.29) 网关侧(clash 消费,不面向客户端)
OpenClash / clash(meta) 192.168.66.1(gfw) gateway 自身/被劫持流量的 fake-ip + 代理;DNS 走 dnsmasq→clash #7874 仅网关侧与 VLAN10

关键事实(全部实测):

  • LAN 客户端 DNS 直连 66.36,不经过 gfw(EdgeRouter service dns forwarding cache 512,通告 .36)。
  • AGH 上游:DoH dns.alidns.com(→223.5.5.5/223.6.6.6)+ doh.pub(→120.53.53.53/1.12.12.12), upstream_mode: load_balancefastest_timeout: 1supstream_timeout: 10s;bootstrap 223.5.5.5/223.6.6.6(公网 IP,无自举循环);兜底 DoH adg.chans.xyz(→hk2.chans.xyz154.36.174.161)。 DNS 监听 UDP/TCP v4 only(0.0.0.0:53),无 v6 监听;enable_dnssec: false;cache 4 MB;ratelimit 20。
  • AGH 宿主出网:默认路由 via 192.168.66.254(EdgeRouter),直连,不经 gfw;DoH 实测可达 (223.5.5.5:443 → HTTP 400/0.05s,120.53.53.53 → 502/0.06s,adg.chans.xyz 冷连接 ~3.5s)。
  • gfw 自身出网:OpenClash openclash_mangle_output 对非本地区域/国内 IP 流量统一 mark 0x162 → tproxy 127.0.0.1:7895(gfw 自身流量默认走代理,含 clash 的 nameserver-policy DoH);mosdns 的上游(AGH .36 本地区域、223.5.5.5 国内 IP)均被 bypass,保持直连。
  • gfw DNS 链:server=127.0.0.1#7874(dnsmasq)→ clash:nameserver: [127.0.0.1:6052](mosdns)、 default-nameserver: [127.0.0.1:6052]nameserver-policy 国外域名 → DoH https://1.1.1.1/dns-queryenhanced-mode: fake-ip(198.18.0.1/16)、ipv6: false;nft 有 UDP/53 hijack → dnsmasq。
  • AGH rewrites(实测):hass.windy.lan/hass.local192.168.55.11;dns.windy.lan.36; ubnt.windy.lan.46;gfw.windy.lan.1;nas.windy.local.32
  • 拦截:仅启用 AdGuard DNS filter(filter_1);实测 doubleclick.net/googleadservices.com0.0.0.0

现状缺口(实测确认):

  1. AGH 上游是固定 DoH,无"国内/国外分流"能力;国外域名解析质量依赖唯一兜底路径。
  2. 兜底失效(kill-test 证实):主上游黑洞时,兜底 adg.chans.xyz 在客户端 15s 窗口内不生效 (upstream_timeout: 10s + TCP 重试行为),缓存未命中查询无有界降级——见 §8。
  3. 国外域名 AAAA 经国内路径全部置空(见 §8),v6 解析缺位。

2. 最终裁决对齐(用户定稿 2026-08-12)

# 裁决 本issue处理
1 保留 AGH .36 为唯一 LAN DNS 入口(现有方案增强版),不改 EdgeRouter DHCP 通告 现状保持;本期零改动
2 否决"AGH 全局转发到 Clash fake-IP"——DNS 平面必须与流量转发平面一致 分层方案(§4)明确 AGH 上游为真实 IP 解析路径,不与 fake-ip 混用
3 AGH → mosdns 仅为二期可选项(经实测确有需求后启用) §4 为二期方案;§8 kill-test 已给出"实测需求"证据(降级缺口)
4 代理 VLAN10 将来用独立 OpenClash DNS 平面(fake-ip + TPROXY),不污染普通 LAN 现状即此(dnsmasq→clash,非面向 LAN 客户端);文档记录
5 删除或明确禁用 .1 上未使用的 mosdns ⚠️ 前提修正:mosdns 是 clash 的 nameserver,处于活动链路(§1)。处置改为正式纳管并文档化(本文件 + hosts/gfw.windy.lan.md),不删除
6 先完成验证再改动生产路径 本期完成全部 Phase 0 验证(§8),未改任何生产 DNS 路径
7 建立 home.arpa 内部域(替代 .local) 后续任务:当前命名空间为 .lan(AGH rewrites + EdgeRouter DHCP domain),hass.local 兼容保留至迁移完成;home.arpa 需联动 AGH rewrites、DHCP domain、客户端,另行排期
8 高可用时增加第二个等价 AGH(独立物理故障域) 备用方案,记录不实施

3. 两个候选方案评估

方案 A:AGH 单独作为统一入口(现状演进)

  • 优点:单解析点、面板/拦截/日志集中、维护简单。
  • 缺点:AGH 对 geo 分流 + 防污染支持弱(官方定位是"过滤/家长控制")。固定 DoH 上游无法按域名 region 选路;且 §8 kill-test 显示主上游全挂时缓存未命中查询无有界降级。→ 不足以解决防污染/分流/降级问题。

方案 B:mosdns 作为智能上游分流器

mosdns(v5)用 sequence 编排:geosite/geoip 匹配器 → 国内域名转发国内 DoH、国外域名转发加密 DoH(防污染),可加 cachereject

  • 优点:真正解决"国内快 / 国外不被污染"的分流;性能高。
  • 缺点:纯转发器,无 Web 面板、无每客户端统计、拦截靠域名表。→ 单独当入口会退回原始体验。

结论:两个方案互补,不是二选一。 单用 A 无法分流防污染且降级无界;单用 B 失去 AGH 管理体验。

4. 二期可选项:分层架构(AGH 前端 + mosdns 后端,经实测需求后启用)

局域网客户端(DHCP DNS = 192.168.66.36)
        │
        ▼
AdGuard Home (66.36)      ── 前端:广告/过滤、拦截表、每客户端统计、Web 面板
   │  上游 = mosdns
   ▼
mosdns(66.36 伴生容器)      ── 后端:智能分流 + 防污染
   │  - geosite:cn        → 国内 DoH/UDP(aliDNS / 腾讯 DNSPod)
   │  - 其他              → 加密 DoH(自建 adg.chans.xyz 等)
   ▼
   上游 DoH

职责分离:

  • AGH = 策略/拦截/可观测(拦截表、每客户端日志、面板)。
  • mosdns = 智能转发(geo 分流 + 加密防污染 + 内置 cache,可显著缩短降级窗口)。
  • OpenClash(gfw)= 代理选路(fake-ip + 规则)。与 DNS 解析选上游是两个独立决策,分开放最干净。

部署位置:mosdns 与 AGH 同机(66.36 伴生容器),而非 gfw(.1):单点即 AGH 所在;不受网关重启/ OpenClash churn 影响;可纳入现有 compose/ansible 管理;不占用 OpenWrt 资源。放 gfw 会与 clash 的 DNS 处理互相干扰、耦合,且网关重启即断全 LAN DNS。不推荐放 .1。

启用条件(kill-test 实测需求,§8):主上游全挂时,当前 AGH 单入口对缓存未命中查询无有界降级。 分层方案(或下调 upstream_timeout + 改 failover 模式)可修;启用与否由用户在二期决定。

5. 更优替代方案(一并考虑)

  1. 分层(推荐二期,见 §4):AGH(66.36)→ mosdns(66.36 伴生)→ 上游。体验最好、职责最清。
  2. 纯 mosdns + 前端面板:损失拦截/统计管理体验。不推荐用于替换。
  3. AGH 只挂一个带分流的上游(第三方 DoH 聚合):失去可控性且不可信。不推荐做主路径。
  4. 全部交给 OpenClash fake-ip,关闭 AGH:让"代理网关"成为全 LAN DNS 单点;且 AGH 拦截/日志也没了。不推荐。

6. mosdns 配置要点(mosdns v5,二期实施预留)

核心是 sequence + 上游拆分 + 缓存 + 屏蔽:

plugins:
  - tag: main
    type: sequence
    args:
      - exec: cache 1024            # 缓存加速
      # 国内分流:命中 geosite:cn → 国内 DoH
      - matches: [ qname &geosite:cn ]
        exec: forward https://dns.alidns.com/dns-query
      # 广告域名屏蔽交 AGH 前置,不重复维护
      # 其余(国外)→ 加密 DoH 防污染
      - exec: forward https://adg.chans.xyz/dns-query
  - type: udp_server
    args: { entry: main, listen: "127.0.0.1:5353" }
  - type: tcp_server
    args: { entry: main, listen: "127.0.0.1:5353" }

要点:

  • 上游可加 upstreamconcurrent > 1 与多地址故障切换;mosdns 自带 cache,能保证上游故障时 缓存命中仍即时应答(对应 §8 认定的降级缺口)。
  • geosite:cn / geoip:cn 数据自动更新;国内 aliDNS/腾讯,国外可用自建 adg.chans.xyz(实测 唯一能返回国外 AAAA 的路径,§8)。
  • 屏蔽交 AGH 前置,AGH 与 mosdns 不各自维护拦截表。

7. 迁移 / 实施顺序(二期,待用户确认启用)

  1. 在 66.36 起 mosdns 伴生容器(/opt/mosdns + compose,按 digest 固定镜像,纳入 ansible)。
  2. AGH「上游 DNS 服务器」改为指向 mosdns(127.0.0.1:5353,bootstrap 仍用公网 IP,避免 AGH → mosdns → AGH 死循环);只保留一条语义一致的上游路径,保持可回滚(备份 yaml + --check-config)。
  3. 验证:国内域名、国外域名、被拦截域名、每客户端日志、AAA A 解析(§8 基线)。
  4. 回归:EdgeRouter 通告不变(仍 .36),LAN 客户端无感;重启 AGH/mosdns 单点验证(§8 kill-test 模板)。
  5. 上线后重跑 §8 kill-test,确认降级窗口有界。

8. Phase 0 验证证据(2026-08-12 全部实测)

8.1 基线与功能

结果
rewrites:hass.windy.lan / hass.local 192.168.55.11 (兼容保留)
rewrites:dns.windy.lan / gfw.windy.lan / ubnt.windy.lan / nas.windy.local .36 / .1 / .46 / .32
国内解析 taobao.com(经 AGH) 真实 CN IP(59.82.x 等)
国外解析 google.com / github.com(经 AGH) 真实 IP(142.250.x / 20.205.x),无 fake-IP 泄漏
广告拦截 doubleclick.net / googleadservices.com 0.0.0.0
clash 7874 google.com 198.18.1.101(fake-ip,仅网关/VLAN10 平面)
clash 7874 taobao.com 真实 IP(经 mosdns→AGH)
dnsmasq :53(.1)google.com / taobao.com fake-ip / 真实 IP
mosdns 6052 直连 taobao.com / google.com 真实 IP(59.82.x / 142.250.73.78)
DNSSEC:dnssec-failed.org(经 AGH) 返回正常应答 96.99.227.255(非 SERVFAIL)→ 当前路径不校验,W1N-40 结论复现,维持关闭

8.2 出口路径与 fake-IP 泄漏

  • AGH 宿主默认路由 via 192.168.66.254(EdgeRouter),直连出网,不经 gfw;DoH 端点实测可达 (见 §1)。LAN 客户端经 AGH 的解析结果全部为真实 IP,无 198.18/16 泄漏。
  • gfw 自身流量默认进代理(openclash_mangle_output mark 0x162 → tproxy :7895), clash nameserver-policy 的 1.1.1.1 DoH 实测 35ms 可达(走代理链路,不依赖直连)。
  • mosdns 上游(AGH .36223.5.5.5)命中本地/国内 bypass 规则,保持直连——设计意图达成。

8.3 IPv6 / RDNSS / AAAA

  • LAN 有 IPv6 SLAAC(EdgeRouter dhcpv6-pd /60 → eth0 host-address + switch0,service slaac, 无 RDNSS/dns-server 通告);.36 有全局 v6 地址 + RA 默认路由。
  • RDNSS 未通告 → v6 客户端无 v6 DNS,回退 v4 DNS(.36);AGH 仅监听 0.0.0.0:53(v4 only),无 v6 DNS 服务。
  • AAAA 解析实测:baidu.com 公网本就无 AAAA(dns.google NOERROR/0,权威 NS 而已); taobao.com AAAA 经国内路径正常(2408:4001:f10::6f 等);国外域名(google.com)经 223.5.5.5 UDP、alidns DoH、8.8.8.8 UDP 全部返回空,而 dns.google 与 adg.chans.xyz DoH 均能返回 2404:6800:4005:81a::200e国内路径对国外域 AAAA 置空;adg.chans.xyz 兜底是当前唯一能返回国外 AAAA 的路径。clash ipv6: false 亦不返回 AAAA。

8.4 自举(bootstrap)循环

  • AGH bootstrap_dns: [223.5.5.5, 223.6.6.6](公网 IP,非 AGH 自身)→ 无自举循环;AGH 解析 DoH 主机名不经过自身。二期方案要求 AGH→mosdns 时 bootstrap 仍用公网 IP(§7)。

8.5 Kill-test 矩阵(2026-08-12,全部实测)

# 场景 结果
1 重启 .1 mosdns(init.d) 直连 6052 与 clash 链恢复
2 重启 .1 dnsmasq 真实 IP 与 fake-ip 双路径恢复
3 kill .1 clash 核心 LAN DNS(AGH)不受影响;gfw dnsmasq→clash 有界 3s 失败(无卡死);OpenClash watchdog ~15s 自动拉起
4 stop/start .1 OpenClash DNS 平面独立于代理;clash 与 tproxy 规则恢复
5 重启 .36 AGH 容器 全量恢复:rewrites/拦截/国内外解析/DNSSEC 行为不变
6 黑洞 alidns DoH(223.5.5.5/223.6.6.6:443) ~0.5s 内经 doh.pub 应答(load_balance 生效)
7 黑洞全部主上游,兜底存活(adg.chans.xyz) ⚠️ 客户端 15s 内无应答——兜底未在窗口内生效
8 黑洞全部上游(含兜底),缓存未命中 ⚠️ 25s 内无应答、无 SERVFAIL——解析器对缓存未命中查询"卡死"
9 黑洞全部上游,缓存命中 瞬时 NOERROR(cache 兜底)

结论(Phase 0 门禁): 国内解析在代理停止/上游单点故障/组件重启下均维持可用; 但**"主上游全挂"时缓存未命中查询无有界降级**——upstream_timeout: 10s 与 TCP 重试行为使 兜底 adg.chans.xyz 在实践中无法在客户端期望窗口内生效。这是 §4 二期分层方案(或下调 upstream_timeout + failover 模式)的实测需求依据;按最终裁决,本期不改生产路径。

9. 风险与备注

  • mosdns 仅监听 127.0.0.1(不对外),由 clash 消费;二期若启用,保持同样的边界,避免 LAN 出现两套入口。
  • AGH 上游指向本机 mosdns 时务必配公网 bootstrap,否则自举死循环。
  • 本方案不改 EdgeRouter DHCP/通告、不改 gfw OpenClash 代理规则,只动 66.36 上的 DNS 链路,风险可控。
  • 已知降级缺口(§8.5 #7/#8):主上游全挂时缓存未命中查询无有界降级;启用二期前,LAN 客户端会感知 超时(约 10s+)。缓解:AGH cache 已覆盖高频域;根治需二期。
  • 与 W1N-40「审查并修正 AdGuard Home」联动:该 issue 侧重 AGH 本身,本 issue 侧重整体 DNS 分层。