Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d43fc5aa01 | ||
|
|
ab0fd16a92 | ||
|
|
9c1d5ab6fe |
@@ -0,0 +1,118 @@
|
|||||||
|
# 内网 DNS 架构调研与优化建议
|
||||||
|
|
||||||
|
> 状态:2026-08-12 调研,Linear **W1N-56**。基于网络工程师视角,方案待实施评审。
|
||||||
|
> 2026-08-12 现场核查修正:gfw 上 mosdns 已并入 OpenClash DNS 链(作为 clash 的
|
||||||
|
> `nameserver`,DIRECT 规则真实 IP 解析用),**不再闲置**;推荐方案(AGH 前端 +
|
||||||
|
> `.36` 伴生 mosdns 后端)仍待评审落地。
|
||||||
|
> 相关:`docs/lan-overview.md`、`hosts/dns.windy.lan.md`、`hosts/gfw.windy.lan.md`。
|
||||||
|
|
||||||
|
## 1. 现状(实测)
|
||||||
|
|
||||||
|
| 角色 | 部署 | 职责 | 是否在活动路径 |
|
||||||
|
|------|------|------|----------------|
|
||||||
|
| **AdGuard Home** | `192.168.66.36`(PVE VM 120,Docker host 网络) | EdgeRouter DHCP 通告给 LAN55/66 客户端的 DNS;广告/过滤、查询统计、Web 面板 | ✅ **是** |
|
||||||
|
| **mosdns** | `192.168.66.1`(gfw OpenWrt)监听 `127.0.0.1:6052` | OpenClash custom DNS 的 `nameserver`(DIRECT 规则真实 IP 分流:国内→AGH `.36`,国外→国内公网 DNS `223.5.5.5`/`119.29.29.29`) | ✅ 网关侧(clash 消费,不面向客户端) |
|
||||||
|
| **OpenClash / clash(meta)** | `192.168.66.1`(gfw) | gateway 自身/被劫持流量的 fake-ip + 代理,DNS 走 dnsmasq→clash `#7874` | 仅网关侧 |
|
||||||
|
|
||||||
|
**关键事实:** LAN 客户端 DNS 直连 `66.36`,**不经过** gfw(EdgeRouter `service dns forwarding` cache 512,通告 `.36`)。所以 gfw/clash 的 fake-ip 分流对"直连 AGH 的客户端"不起作用;gfw 上 mosdns 作为 clash 的 `nameserver` 供 DIRECT 规则连接的真实 IP 解析用(国内→AGH,国外→国内公网 DNS),不面向 LAN 客户端。
|
||||||
|
|
||||||
|
**现状缺口:**
|
||||||
|
1. AGH 上游是**固定 DoH**(alidns/doh.pub,兜底 adg.chans.xyz),**没有"国内/国外分流"能力** → 国外域名解析易受 DNS 污染/时延差,也无法为不同 region 选最优上游。
|
||||||
|
2. 国内/国外分流逻辑(geo)与代理分流逻辑(clash fake-ip)混在网关上,职责不清。
|
||||||
|
|
||||||
|
## 2. 两个候选方案评估
|
||||||
|
|
||||||
|
### 方案 A:AGH 单独作为统一入口(现状演进)
|
||||||
|
- 优点:单解析点、面板/拦截/日志集中、维护简单。
|
||||||
|
- 缺点:AGH 对 geo 分流 + 防污染支持弱(官方定位是"过滤/家长控制",见 adguard README "Encrypted DNS upstream... requires additional software")。固定 DoH 上游无法按域名 region 选路。→ **不足以解决防污染/分流问题。**
|
||||||
|
|
||||||
|
### 方案 B:mosdns 作为智能上游分流器
|
||||||
|
mosdns(v5)用 `sequence` 编排:`geosite/geoip` 匹配器 → 国内域名转发国内 DoH、国外域名转发加密 DoH(防污染),可加 `cache`、`reject`(屏蔽)。
|
||||||
|
- 优点:真正解决"国内快 / 国外不被污染"的分流;性能高(百万域名表也不卡)。
|
||||||
|
- 缺点:纯转发器,无 Web 面板、无每客户端统计、拦截要靠域名表(不如 AGH 体验)。→ 单独当入口会退回原始体验。
|
||||||
|
|
||||||
|
**结论:两个方案是互补的,不是二选一。** 单用 A 无法分流防污染,单用 B 失去 AGH 的管理体验。
|
||||||
|
|
||||||
|
## 3. 推荐:分层架构(AGH 前端 + mosdns 后端)
|
||||||
|
|
||||||
|
```
|
||||||
|
局域网客户端(DHCP DNS = 192.168.66.36)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
AdGuard Home (66.36) ── 前端:广告/过滤、拦截表、每客户端统计、Web 面板
|
||||||
|
│ 上游 = mosdns
|
||||||
|
▼
|
||||||
|
mosdns(66.36 伴生容器) ── 后端:智能分流 + 防污染
|
||||||
|
│ - geosite:cn → 国内 DoH/UDP(aliDNS / 腾讯 DNSPod)
|
||||||
|
│ - 其他 → 加密 DoH(Cloudflare/Google/自建 adg.chans.xyz)
|
||||||
|
▼
|
||||||
|
上游 DoH
|
||||||
|
```
|
||||||
|
|
||||||
|
职责分离,每个工具只做自己最擅长的事:
|
||||||
|
- **AGH = 策略/拦截/可观测**(拦截表、每客户端日志、面板)。AGH 原生干不了"按域名选路",所以不做分流。
|
||||||
|
- **mosdns = 智能转发**(geo 分流 + 加密防污染)。不用它当入口,所以保持 AGH 的 UX。
|
||||||
|
- **OpenClash(gfw)= 代理选路**(fake-ip + 规则决定"哪些流量走代理")。与"DNS 解析选上游"是**两个独立决策**,分开放在不同工具最干净——DNS 解析在 66.36 做,代理路由在网关做,互不耦合。
|
||||||
|
|
||||||
|
### 推荐部署位置:mosdns 与 AGH 同机(66.36),而非 gf(.1)
|
||||||
|
|
||||||
|
| 位置 | 评价 |
|
||||||
|
|------|------|
|
||||||
|
| **66.36 伴生容器(推荐)** | 单点即 AGH 所在;AGH→mosdns 走本机/近端一跳;不受网关重启/OpenClash churn 影响;可纳入现有 ansible compose 管理;不占用 OpenWrt 资源 |
|
||||||
|
| gf(.1) | 虽近网络边缘,但该网关已有 clash fake-ip + 多种劫持规则,再叠 mosdns 会与 clash 的 DNS 处理互相干扰、耦合;且网关重启即断 DNS(影响整个 LAN)。**不推荐** |
|
||||||
|
|
||||||
|
> 注意:若把 mosdns 放 gfw,必须先理清与 OpenClash `dnsmasq→clash #7874` + `nft fw4 DNS-hijack` 的先后/覆盖关系,否则会出现"部分设备解析走了 clash、部分走了 mosdns"的混乱。放 66.36 则完全避开这个冲突。
|
||||||
|
|
||||||
|
## 4. 更优替代方案(也一并考虑)
|
||||||
|
|
||||||
|
1. **分层(推荐,见上)**:AGH(66.36)→ mosdns(66.36 伴生)→ 上游。体验最好、职责最清。
|
||||||
|
2. **纯 mosdns + 前端面板**:不用 AGH,用 mosdns + 其他统计面板。→ 会明显损失拦截/统计管理体验,除非你讨厌 AGH 的 Docker 部署。**不推荐**用于替换。
|
||||||
|
3. **AGH 只挂一个带分流的上游(第三方 DoH 聚合)**:例如接一个已做分流的公共 DoH。→ 失去可控性,且不可信。不推荐做主路径。
|
||||||
|
4. **全部交给 OpenClash fake-ip,关闭 AGH**:把 LAN 客户端 DNS 指到 gfw。→ 让"代理网关"成为全 LAN DNS 单点,网关重启/代理抖动整个内网断网;且 AGH 的拦截/日志也没了。**不推荐。**
|
||||||
|
|
||||||
|
## 5. mosdns 配置要点(mosdns v5,预留实施)
|
||||||
|
|
||||||
|
核心是 `sequence` + 上游拆分 + 缓存 + 屏蔽:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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 前置拦截,二选一)
|
||||||
|
# - matches: [ qname &./blocklist.txt ]
|
||||||
|
# exec: reject 3
|
||||||
|
# 其余(国外)→ 加密 DoH 防污染
|
||||||
|
- exec: forward https://1.1.1.1/dns-query
|
||||||
|
# 备选国外上游/兜底
|
||||||
|
- matches: [ has_resp ]
|
||||||
|
exec: accept
|
||||||
|
- exec: forward_addr https://208.67.222.222:443/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" }
|
||||||
|
```
|
||||||
|
|
||||||
|
要点:
|
||||||
|
- 上游可加 `upstream` 的 `concurrent > 1` 与 `addr` 做多/故障切换。
|
||||||
|
- `geosite:cn` / `geoip:cn` 数据插件自动从 repo 更新;国内用 aliDNS/腾讯,国外用 DoH(Cloudflare/Google/自建 adg.chans.xyz)。
|
||||||
|
- 屏蔽交由 AGH 前置(推荐),不要 AGH 和 mosdns 都自己维护一套拦截表(重复)。
|
||||||
|
|
||||||
|
## 6. 迁移 / 实施顺序(待评审)
|
||||||
|
|
||||||
|
1. 在 66.36 起 mosdns 伴生容器(`/opt/mosdns` + compose,固定 digest,纳入 ansible)。
|
||||||
|
2. AGH「上游 DNS 服务器」改为指向 mosdns(`http://127.0.0.1:5353/dns-query` 或 `127.0.0.1:5353`)。AGH 的 `bootstrap` 仍用公网 IP(避免 AGH → mosdns → AGH 死循环)。
|
||||||
|
3. 验证:国内域名(如 `taobao.com`)、国外域名(如 `google.com`)、被拦截域名、每客户端日志。
|
||||||
|
4. 确认后,`disable`/移除 gfw 上闲置的 mosdns(6052)以免混淆。
|
||||||
|
5. 回归:EdgeRouter 通告不变(仍 `.36`),因此 LAN 客户端无感;重启 AGH/mosdns 单点验证。
|
||||||
|
|
||||||
|
## 7. 风险与备注
|
||||||
|
- mosdns 仅监听 `127.0.0.1`(不对外),由 AGH 消费;避免 LAN 直连 mosdns 造成两套入口。
|
||||||
|
- AGH 上游指向本机 mosdns 时,务必配 bootstrap 公网 IP,否则自举死循环。
|
||||||
|
- 本方案不改 EdgeRouter DHCP/通告,不改 gfw OpenClash 代理规则,只动 66.36 上的 DNS 链路,风险可控。
|
||||||
|
- 与 W1N-40「审查并修正 AdGuard Home」联动:该 issue 侧重 AGH 本身,本 issue 侧重整体 DNS 分层。
|
||||||
@@ -32,10 +32,17 @@ Do not enable AdGuard Home DHCP unless the existing EdgeRouter DHCP service is
|
|||||||
explicitly migrated and disabled first.
|
explicitly migrated and disabled first.
|
||||||
|
|
||||||
`agh-ui-access.service` loads `/etc/nftables-agh-ui-access.nft`. It permits
|
`agh-ui-access.service` loads `/etc/nftables-agh-ui-access.nft`. It permits
|
||||||
only `192.168.66.0/24` to TCP/80 and drops other TCP/80 input. It deliberately
|
`192.168.66.0/24` (LAN66) and `192.168.55.0/24` (LAN55, for Home Assistant
|
||||||
|
integration) to TCP/80 and drops other TCP/80 input. It deliberately
|
||||||
does **not** restrict DNS, SSH, Docker, or Mihomo ports. Keep it isolated from
|
does **not** restrict DNS, SSH, Docker, or Mihomo ports. Keep it isolated from
|
||||||
Docker-managed nftables tables.
|
Docker-managed nftables tables.
|
||||||
|
|
||||||
|
> 2026-08-12: added `192.168.55.0/24` allow so HAOS (`192.168.55.11`) can reach
|
||||||
|
the HTTP API on `:80` for the Home Assistant AdGuard Home integration; applied
|
||||||
|
via `sudo systemctl restart agh-ui-access.service` (file edited first, then
|
||||||
|
reloaded; syntax verified with `nft -c`). Other firewalls (EdgeRouter LAN_IN/
|
||||||
|
LAN_OUT inactive, PVE zero rules) were already open for LAN55->LAN66.
|
||||||
|
|
||||||
Current query-log policy is 14 days with anonymized client IPs. Check free
|
Current query-log policy is 14 days with anonymized client IPs. Check free
|
||||||
space before increasing retention. DNSSEC is disabled because the selected
|
space before increasing retention. DNSSEC is disabled because the selected
|
||||||
upstream path did not pass the known-bad-signature validation check; do not
|
upstream path did not pass the known-bad-signature validation check; do not
|
||||||
|
|||||||
+20
-15
@@ -8,7 +8,7 @@
|
|||||||
| IPv4 | `192.168.66.1` |
|
| IPv4 | `192.168.66.1` |
|
||||||
| SSH | `ssh -4 root@192.168.66.1` (key-only, verified 2026-08-06) |
|
| SSH | `ssh -4 root@192.168.66.1` (key-only, verified 2026-08-06) |
|
||||||
| OS | ImmortalWrt 25.12.0 (r37854), Linux `6.12.87`, x86/64 |
|
| OS | ImmortalWrt 25.12.0 (r37854), Linux `6.12.87`, x86/64 |
|
||||||
| **Host** | **PVE VM 140 (`gfw`)** — dual NIC: `net0`→vmbr0(LAN66), `net1`→vmbr1(LAN55) (verified 2026-08-09) |
|
| **Host** | **PVE VM 140 (`gfw`)** — 3 NICs: `net0`→vmbr0(LAN66/eth0), `net1`→vmbr1(LAN55/eth1, up but unaddressed), `net2`→VLAN10/`ubunt_upg`(eth2, `192.168.10.1/24`) (topology 2026-08-09; eth2/VLAN10 live verified 2026-08-11) |
|
||||||
|
|
||||||
Do not store the root password in this repository.
|
Do not store the root password in this repository.
|
||||||
|
|
||||||
@@ -25,8 +25,11 @@ OpenClash runs `/etc/openclash/clash` (clash_meta core) with configuration
|
|||||||
- Mode: **fake-ip + TPROXY transparent proxy** (`operation_mode=fake-ip`,
|
- Mode: **fake-ip + TPROXY transparent proxy** (`operation_mode=fake-ip`,
|
||||||
`en_mode=fake-ip`, `proxy_mode=rule`); fake-ip network `198.18.0.0/16`
|
`en_mode=fake-ip`, `proxy_mode=rule`); fake-ip network `198.18.0.0/16`
|
||||||
- DNS path: dnsmasq → clash DNS `127.0.0.1#7874` (`server=127.0.0.1#7874` in
|
- DNS path: dnsmasq → clash DNS `127.0.0.1#7874` (`server=127.0.0.1#7874` in
|
||||||
dnsmasq config); `mosdns` also listens on `127.0.0.1:6052` but is not the
|
dnsmasq config); OpenClash custom DNS uses `mosdns` on `127.0.0.1:6052` as its
|
||||||
active resolver path
|
`nameserver`/`default-nameserver` for DIRECT-rule real-IP resolution
|
||||||
|
(`/etc/mosdns/config.yaml`): domestic domains → AGH `.36:53`, foreign →
|
||||||
|
`223.5.5.5`/`119.29.29.29` (Chinese public DNS). mosdns is **not** in the
|
||||||
|
client query path — LAN/VLAN10 clients receive fake-ip from clash :7874.
|
||||||
- nft: OpenClash injects TPROXY/redirect + DNS-hijack rules into
|
- nft: OpenClash injects TPROXY/redirect + DNS-hijack rules into
|
||||||
`table inet fw4`; a residual `table inet passwall` exists with 0 packets (unused)
|
`table inet fw4`; a residual `table inet passwall` exists with 0 packets (unused)
|
||||||
|
|
||||||
@@ -43,20 +46,22 @@ OpenClash runs `/etc/openclash/clash` (clash_meta core) with configuration
|
|||||||
`8443` is not an OpenClash listener and has no runtime nftables forwarding rule.
|
`8443` is not an OpenClash listener and has no runtime nftables forwarding rule.
|
||||||
It is included only in OpenClash's common TLS-sniffing port list.
|
It is included only in OpenClash's common TLS-sniffing port list.
|
||||||
|
|
||||||
## VLAN 10 Wi-Fi feasibility
|
## VLAN 10 Wi-Fi
|
||||||
|
|
||||||
`gfw` is a VM attached to untagged LAN 66, rather than a physical VLAN-trunk
|
`gfw`'s third NIC `eth2` hosts the `ubunt_upg` interface at `192.168.10.1/24`,
|
||||||
endpoint. The U6 Lite likewise reaches the ER-X over LAN 66, whose DHCP
|
serving the dedicated `ubnt-upg` SSID VLAN 10 (untagged access path from a
|
||||||
service supplies client addresses. Therefore `gfw` cannot currently receive an
|
VLAN-capable switch/trunk; AP management stays untagged on LAN66). The
|
||||||
SSID's VLAN 10 traffic merely by creating an `eth0.10` interface inside the VM.
|
`ubunt_upg` zone runs the **only** DHCP server for `192.168.10.0/24` (UDP/67),
|
||||||
|
allows DNS (53), and applies `192.168.10.0/24 → eth0 masquerade` (NAT) for
|
||||||
|
Internet egress. `forward_ubunt_upg` isolates VLAN10 from LAN66/55 and RFC1918
|
||||||
|
(deny counters 0, `accept_to_lan` passes).
|
||||||
|
|
||||||
Do not treat a local `eth0.10`/`192.168.10.1` configuration as a deployable
|
Live-verified 2026-08-11: an `ubnt-upg` client received `192.168.10.168` (lease
|
||||||
Wi-Fi gateway unless the hypervisor/vSwitch and the complete physical path to
|
in `/tmp/dhcp.leases`), the `192.168.10.0/24 masquerade` counter climbed
|
||||||
the AP have first been configured and verified to carry tagged VLAN 10. The
|
(215 pkts/42KB), and the LAN55/LAN66 deny counters stayed 0 → VLAN10→LAN
|
||||||
`ubnt-upg` test receiving a `192.168.66.x` lease was the expected consequence
|
isolation holds. See
|
||||||
of the available untagged path, not evidence that this host should compete
|
[docs/lan-se5420-deployment-guide.md](../docs/lan-se5420-deployment-guide.md),
|
||||||
with ER-X DHCP. See
|
[docs/unifi-openwrt-vlan10-implementation-examples.md](../docs/unifi-openwrt-vlan10-implementation-examples.md)
|
||||||
[UniFi Network: Dedicated Wi-Fi through a third-party gateway](../docs/unifi-network.md#dedicated-wi-fi-through-a-third-party-gateway).
|
|
||||||
|
|
||||||
## Operational note
|
## Operational note
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user