家庭网络搭建03-踩坑两年:DNS 慢、流媒体卡、规则难维护
Viewed: loading...
13 minutes to read
本文由 AI 优化组织完成,非个人完整编写,AI 参与度:90%
Hello 朋友们,上一篇家庭网络系列写到了软路由的基本原理,也搭了一套「看起来能跑」的方案。这两年一直在用,大部分时候确实挺顺,但有几个问题一直在后台静静地折腾我——有时候 GitHub 要等将近一分钟才能开、小红书在家 WiFi 下图片不加载、换了个 VPN 服务商自定义规则全失效……每次出问题都感觉「就差一点」,但就是搞不清楚根在哪里。
趁着这次把三件事全搞清楚了,顺手整理成这篇踩坑记录。
如果还没看过前两篇的朋友,可以先补补背景:
先说说家里的网络是怎么布的
家里用了两台路由器。一台是普通的主路由,负责连光猫、管全家上网;另一台是一个小主机,跑着「软路由」,专门负责让网络变聪明——帮你决定哪些流量直连国内服务器,哪些走代理绕出去。
这次换了更好的主路由之后,顺带解决了一个以前很烦的操作:以前每台设备想走代理,得手动去改网络设置,改错了还会断网。现在直接在路由器上建了两个 WiFi 信号,一个普通的,一个「科学上网专用的」,连哪个就走哪条路,完全自动,手机根本不用动任何设置。软路由要是出问题了,也只需要切换一下 WiFi,5 秒恢复正常上网。

技术细节
主路由从小米 AX3600 换成了优倍快(Ubiquiti UniFi),旁路由这套没动,OpenClash 跑 Fake-IP Mix 模式,AdGuard Home 负责 DNS 广告过滤。UniFi 支持划分多个子网,每个子网可以单独配置 DHCP 下发的 DNS 和网关,所以能做到连上某个 SSID 就自动走全链路。
DNS 的完整链路是:
设备 └─ dnsmasq(53) ← OpenWRT 内置,DHCP 告诉设备 DNS 在路由器上 └─ OpenClash(7874) ← 实现 Fake-IP,必须在此拦截 └─ ADG(5335) ← 广告过滤 └─ 223.5.5.5 ← 真实上游OpenClash 必须夹在 dnsmasq 和 ADG 之间,因为 Fake-IP 的核心逻辑要求它必须是 DNS 链路里最靠近设备的那一层,否则假 IP 机制完全没法工作。4 跳全在本地回环或局域网内,延迟是微秒级,感知不到。
「玄学的一分钟」:等很久,突然通了
有一段时间,GitHub 打开要转圈将近一分钟,有时候 Notion 也这样。换节点、重连 WiFi 都没用,但一切手机流量就立刻好——说明不是节点的问题,锅在路由器上。
根本原因是路由器「记住了旧地址,不肯更新」。
网站的访问原理有点像查电话本:你说「我要联系 GitHub」,路由器先查自己的记事本(DNS 缓存),有记录就直接拿去用,没有才去问别人。问题是,GitHub 换了地址(比如服务器迁移),路由器的记事本却死记着旧地址,还以为能用,于是你的请求就一直在那儿等——等了将近一分钟才超时放弃,路由器才去重新查了真实地址,连接突然就通了。
更讽刺的是,路由器里还开了一个「聪明」的优化功能:记事本里的记录快过期时,不等真正更新,先把旧地址返回给你,同时偷偷在后台更新。本来是为了加速,结果和「强制延长记忆时间」叠加,就导致你拿着一个早就作废的旧地址去连,必然失败。
修法很简单: 去掉「强制延长记忆时间」(改回自动),关掉那个「先返回旧地址」的优化,顺手清一次缓存。改完之后那个玄学一分钟彻底消失了。

技术细节
问题出在 AdGuard Home 的两个配置项叠加:
Override minimum TTL = 3600:不管域名原始 TTL 是多少,ADG 强制把 DNS 缓存延长到至少一小时。GitHub 的 DNS TTL 是 60 秒,但被强制延到 3600,对方 IP 早已切换,我这边最多要等一小时才能感知到变化。
Optimistic Caching(乐观缓存):缓存过期时不等真正刷新,先把旧 IP 返回,同时后台更新。和 TTL 强制延长叠在一起,旧 IP 被返回,TCP SYN 发出去对方根本不在那个地址,超时要等 63 秒(TCP SYN 重传机制:1+2+4+8+16+32 = 63s)。
修法:ADG DNS 设置里把 Override minimum TTL 改为 0,Optimistic Caching 关掉,Fallback DNS 填 8.8.8.8 和 1.1.1.1 做兜底,手动清空一次 DNS 缓存。
小红书在家里加载慢,切 4G 秒好
家里 WiFi 下刷小红书,图片经常加载不出来,抖音视频也反复缓冲;一切手机流量就立刻正常。问题不是 App,是我的网络链路。
根本原因是路由器「不认识」这些 App 的图片服务器,把它们当成境外流量绕了一大圈。
路由器在分流流量时,有一个兜底规则:不认识的地址,一律走代理出境。小红书、抖音的图片和视频是存在国内服务器上的,本来直连就很快;但路由器没有这些地址的记录,就把它们走了代理——相当于你去隔壁买东西,快递员先把货运到日本再寄回来,当然慢。
修法: 告诉路由器「这些图片服务器是国内的,直接连」,加几条直连规则,图片秒加载。

技术细节
OpenClash 分流规则从上往下匹配,全都没命中就走最底部的
MATCH, Proxies——所有未知流量一律走代理节点。小红书、抖音的图片和视频资源走国内 CDN,这些域名在订阅配置里没有,于是命中 MATCH,绕代理节点出境再回来,不慢才怪。需要加入直连规则的 CDN 域名:
域名 归属 xhscdn.com小红书图片 CDN douyinvod.com抖音视频 douyinpic.com抖音图片 byteimg.com字节系图片 CDN pstatp.com字节系静态资源 kuaishou.com快手 ksyun.com快手云 CDN
真正的麻烦:换了 VPN 服务商,自己加的规则全没了
我平时会自己给路由器「加功能」:让某个网站走代理,让另一个直连。但这些自定义设置之前是和 VPN 服务商的订阅绑在一起的——有一次换了服务商,整个合并流程断掉,自定义规则全部失效。不是规则写错了,是「管道」断了。
更麻烦的是,新服务商的网站有防机器人验证(Cloudflare),之前用的那套自动合并工具直接被挡掉,什么节点都拿不到。
解法是把「用哪些节点」和「规则」彻底分开,互不影响。
节点让路由器自己去订阅服务商那里拉取,它能绕过那个验证;规则单独放在 GitHub 上,路由器定期来取。以后换节点就改一行链接,规则完全不动;想加新规则就去 GitHub 改一行,最多 24 小时自动生效,急着用就重启路由器立即生效。
技术细节
原来的方案是通过 subconverter 把 VPN 订阅和自定义规则合并成一个 Clash 配置文件。问题在于:
- 规则和订阅强绑定,换订阅就断管道
- subconverter 是服务端程序去拉节点,Cloudflare 直接把它挡掉,返回人机验证页,报「No nodes were found!」
新方案:让 OpenClash 自己去拉订阅(有正确的 User-Agent,能过 Cloudflare),规则用 clash.meta 原生的
rule-providers机制独立加载,通过 OpenClash 的「Custom Config Overwrite Scripts」注入配置:#!/bin/sh . /usr/share/openclash/ruby.sh . /usr/share/openclash/log.sh CONFIG_FILE="$1" ruby - "$CONFIG_FILE" << 'ENDRB' require 'yaml' config = YAML.load_file(ARGV[0]) config['rule-providers'] ||= {} config['rule-providers']['peter-proxy'] = { 'type' => 'http', 'behavior' => 'classical', 'url' => 'https://raw.githubusercontent.com/PeterChen1997/peter-config/master/config/clash/rule-providers/proxy-rules.yaml', 'path' => './peter-proxy.yaml', 'interval' => 86400 } config['rule-providers']['peter-direct'] = { 'type' => 'http', 'behavior' => 'classical', 'url' => 'https://raw.githubusercontent.com/PeterChen1997/peter-config/master/config/clash/rule-providers/direct-rules.yaml', 'path' => './peter-direct.yaml', 'interval' => 86400 } config['rules'] ||= [] config['rules'].unshift('RULE-SET,peter-direct,DIRECT') config['rules'].unshift('RULE-SET,peter-proxy,Proxies') File.write(ARGV[0], config.to_yaml) ENDRBGitHub 上的规则文件格式很简单:
# proxy-rules.yaml payload: - DOMAIN-KEYWORD,supabase - DOMAIN-KEYWORD,n8n - DOMAIN-SUFFIX,docker.io - DOMAIN-KEYWORD,instagram# direct-rules.yaml payload: - DOMAIN-SUFFIX,xhscdn.com - DOMAIN-KEYWORD,xiaohongshu - DOMAIN-SUFFIX,douyinvod.com - DOMAIN-KEYWORD,byteimgApply Settings 重启 OpenClash 后,Core Log 里能看到
Start initial provider peter-proxy / peter-direct,流量日志里能确认xiaohongshu.com → RuleSet(peter-direct) → DIRECT,说明规则已生效。
写在最后
这套方案有一个轻微的套娃风险:规则文件托管在 GitHub,而 GitHub 有时需要代理才能访问 hhh。不过规则文件本地缓存 24 小时,就算 GitHub 临时抽风,已有的规则还是照常跑的,影响不大。
感兴趣的朋友可以看看我的 peter-config 仓库,里面有完整的规则文件。
附录:Fake-IP 是什么,和其他模式有什么区别
既然全文提了好几次 Fake-IP,顺便展开讲一下,这是理解整套方案的一个关键概念。
传统代理为什么有局限
你在浏览器里输入 github.com,第一件事是 DNS 解析——浏览器问 DNS「github.com 是哪个 IP?」,拿到 IP 之后再去建 TCP 连接。
Clash 想在这里做流量分流,但如果它只拦截 TCP 连接层,拿到的已经是 IP 了,域名信息丢失了。要用 DOMAIN-KEYWORD,github 这类规则来匹配,就得反向查「这个 IP 是从哪个域名解析来的」,又慢又容易出错,尤其是 CDN 域名一个 IP 对应大量域名,根本查不准。
Fake-IP 怎么解决这个问题
Fake-IP 的思路是在 DNS 阶段就把信息拿住:
设备问 DNS:「github.com 是哪个 IP?」
↓
OpenClash 拦截,不做真实解析
直接返回假 IP:198.18.0.123(RFC 预留测试地址段)
记下映射:198.18.0.123 ↔ github.com
↓
设备拿着 198.18.0.123 发起 TCP 连接
TUN 虚拟网卡拦截这个连接
查表:198.18.0.123 → github.com
匹配规则 → 走代理
代理节点去真正解析并连接 github.com设备全程以为自己在连 198.18.0.123,背后是代理帮你解析了真正的 IP。好处是 DNS 响应极快(不用问上游,直接返回假 IP),域名规则匹配精准,GEOIP 规则也正常。
Fake-IP 的一个坑
198.18.0.0/16 是 IANA 测试地址段,正常网络里不会出现。但一些国内 App、游戏 SDK 或 IoT 设备会校验 IP 是否合法,看到 198.18.x.x 就拒绝连接——直播 App 打不开房间、游戏 SDK 初始化失败,切 4G 就好了,就是这个原因。
解决办法是把有问题的域名加到 fake-ip-filter 列表里,加进去的域名走真实 DNS 解析,不返回假 IP。OpenClash 默认已内置了 NTP、STUN、Nintendo、PlayStation 等常见场景,大部分情况够用。
模式对比:该怎么选
OpenClash 的模式分两个维度:
DNS 模式:
| 模式 | DNS 返回什么 | 优点 | 缺点 |
|---|---|---|---|
| Fake-IP | 假 IP(198.18.x.x) | 快、域名匹配准 | 可能触发「非法 IP」校验 |
| Redir-Host | 真实 IP | 完全兼容,无非法 IP 问题 | 多一次 DNS 解析延迟,GEOIP 规则慢 |
流量拦截方式(Enhance Mode):
| 模式 | 拦截方式 | 覆盖范围 |
|---|---|---|
| TUN | 虚拟网卡,接管所有 IP 流量 | 最全,UDP 也能拦 |
| Mix(混合) | TUN + HTTP/S 系统代理 | 覆盖面略小,兼容性更好 |
| Normal(普通) | 仅 HTTP/S 系统代理 | 只有应用层代理,系统级流量会漏 |
我目前用的是 Fake-IP + Mix:Fake-IP 保证规则匹配速度和准确性,Mix 在 TUN 基础上补了系统代理,兼容性比纯 TUN 更好,偶尔遇到「非法 IP」就在 fake-ip-filter 里加一条。国内 App 多或有 IoT 设备的场景,可以考虑换成 Redir-Host + TUN,牺牲一点 DNS 速度换更好的兼容性。
好啦,这篇写得比前两篇长了不少 hhh,每一个坑都是真实踩过的,希望对有同款配置的朋友有点参考价值。咱们下次见

