我的家庭 DNS 配置方案
家庭组网概述
先简单介绍下家庭组网情况,目前主要是使用一台铭凡 MS-01 作为 All in Boom 的硬件载体。MS-01 自带两个 10G SFP 口,大大增加了可玩性。为了摆脱厚重的运营商光猫,我购置了 10G EPON 猫棒(剑桥 XE-99S)供 MS-01 直接拨号上网。MS-01 的另一个 SFP 口通过 DAC 线缆下联兮克的 2.5G 交换机,再外挂多个小米、红米的 BE7000、AX6000 等无线路由设备,构成完整的家庭网络。
为充分利用 MS-01 的性能,我安装了 PVE(Proxmox Virtual Environment)作为其虚拟化平台,内部主要运行以下几个虚拟实例:
- RouterOS:软路由,通过猫棒直接拨号上网。上海电信的配置相对简单,只需在猫棒中配置正确的 LOID、在 RouterOS 中配置正确的宽带账号密码即可正常拨号上网,没有特别的技术难点。
- Main Server:Debian 服务器,暴露多个端口与 VPS 连接,同时作为外网访问内网的入口点,通过该实例内的服务可以从外部连入内网。
- DNS Server:Debian 服务器,运行 AdGuardHome 与 SmartDNS,用于提供家庭内无污染的 DNS 服务。
从 ImmortalWrt 到 DAE
作为一个坚定的 Surge 用户,长期以来我并不需要过多折腾家庭 DNS 方案,因为 Surge 已经能很好地处理 DNS 解析和流量管理。但在日常使用过程中,确实遇到了部分家庭设备(Linux、Windows)需要正常访问外网的情况,因此我曾添加了一个 ImmortalWrt 实例来解决这个问题。
然而,ImmortalWrt 的各种插件相对混乱,大多提供整套解决方案,出现问题时不易排查,有时会遇到无法正常访问互联网的情况。于是我开始寻找更简单可控的替代方案,最终找到了性能更好(却并不十分知名)的 DAE。
DAE 在内核层面对流量进行分流,能有效提高直连流量的性能。由于 DAE 使用的不是我熟悉的 Fake IP 模式,出于 DNS 配置的洁癖,我开始尝试搭建无污染的家庭 DNS 服务。
DNS 需求分析
在开始构建 DNS 方案前,我的需求非常明确:
- 基本的 DNS 广告过滤功能
- DNS 服务器能够快速返回结果,减少等待时间
- DNS 服务器能够返回精确的结果:解析的 IP 应当是最优的,延迟最低且无污染
经过一段时间的调研和实践,我最终选择了 AdGuardHome 作为前置广告过滤器,SmartDNS 作为主 DNS 请求服务的组合方案。
方案选择理由
广告过滤:为什么选择 AdGuardHome
虽然几乎所有 DNS 服务器都具备广告域名过滤能力,但 AdGuardHome 作为一个成熟稳定的广告过滤工具,具有以下优势:
- 提供可视化界面,可以查看所有 DNS 请求记录
- 规则更新简单直观
- 配置灵活,可定制性强

AdGuardHome
DNS 服务器:SmartDNS vs MosDNS
目前网上流行的 DNS 服务器主要有两个选择:SmartDNS 和 MosDNS。
功能 | SmartDNS | MosDNS |
---|---|---|
简介 | 高性能 DNS 解析加速工具,提供多服务器查询测速最优 IP | 模块化 DNS 解析工具,适用于复杂 DNS 需求 |
主要特点 | 支持多服务器并发查询,测速返回最优的结果 | 规则引擎灵活,支持 DNS 路由降级等高级功能 |
SmartDNS 的一个巧妙设计是:当对多个 DNS 服务器并发查询新域名时,它会先返回 TTL=3 秒的最快结果,确保客户端能够第一时间收到回答。同时,它会对所有 DNS 服务器返回的结果进行测速(通过 TCP 或 ICMP),缓存其最优结果。当 3 秒后客户端 DNS 记录过期,再次发起查询时,SmartDNS 就会直接返回缓存里的最优结果。
在短时间试用两者后,考虑到个人需求,我最终选择了 SmartDNS。在我的使用场景下,可能并不需要 DNS 降级等相对复杂的逻辑,而 DNS 测速功能则更为重要。
关于 DNS 泄漏
我个人认为,不必过度关注 DNS 泄漏问题,更应该关注 DNS 解析结果的准确性与稳定性。虽然提及 DNS 泄漏这个话题可能会引发无休止的争论,但我认为:如果第三方真的要分析你的流量,只需嗅探 TLS 数据包就能做到,没必要为了保证 DNS 100% 无泄漏而牺牲 DNS 解析的速度和体验。对我而言,只需确保敏感域名不在国内递归 DNS 服务器进行解析即可。
DNS 请求策略
结合 SmartDNS 的特性和我的实际需求,我的 DNS 请求策略如下:
- 国内域名:只使用国内递归 DNS 服务器解析,进行测速并使用最优结果
- 国外敏感域名:只使用国外递归 DNS 服务器解析,不进行测速
- 国外普通域名:只使用国外递归 DNS 服务器解析,进行测速并使用最优结果
- 未分类域名:同时使用国内外递归 DNS 服务器解析,进行测速并使用最优结果
策略解析
- 国内域名:对于国内复杂的网络环境,国内 DNS 服务器做了针对性优化,更适合国情。配合 SmartDNS 的测速能力,可获取最优解析结果。
- 国外敏感域名:只使用国外递归 DNS 服务器解析,注意这里不能使用无加密的 DNS 协议。常见的 DOH(DNS over HTTPS)服务基本已被干扰,这里可能需要自建或使用 Cloudflare 提供的 ZeroTrust DNS 服务。由于国外敏感域名解析出的 IP 大多已被墙,且大部分科学上网工具会优先在 VPS 上再次解析请求的域名,因此无需进行测速。
- 国外普通域名:能确定是国外域名的,只使用国外递归 DNS 服务器解析,防止国内结果造成干扰。
- 未分类域名:由于难以准确分辨其属于国内还是国外(特别是使用 CDN 的网站),因此同时使用国内外 DNS 服务器解析,经测速后使用最优结果。因为我家使用的是电信精品网,对国外网站也有相对稳定的访问速度(尤其是香港地区)。对于 CDN 相关资源,使用 Cloudflare DNS(Anycast 技术会选择香港节点)时,也可能返回一些香港的 IP,这些 IP 可以与国内 DNS 服务器返回的 IP 一起参与"竞赛",从中选出最优结果。
具体配置详情
AdGuardHome 配置
AdGuardHome 的配置相对简单:
- 将上游 DNS 地址改为
127.0.0.1:153
(指向 SmartDNS) - 关闭 AdGuardHome 内的所有缓存策略,将缓存管理完全交由 SmartDNS 处理
- 按需添加广告过滤规则,我个人使用了 SKK 大佬维护的规则
SmartDNS 配置
我将 SmartDNS 内的 DNS 服务器分成三组:
- direct 分组:主要处理国内域名,直接使用 UDP DNS
# Aliyun
server 223.5.5.5 -group direct
# DNSPod
server 119.29.29.29 -group direct
- proxy 分组:处理国外敏感域名,使用加密的 DOH
# Cloudflare ZeroTrust
server-https https://xxxx.cloudflare-gateway.com/dns-query -group proxy
- global-lite 分组:主要处理 NTP 相关域名,这类域名请求量巨大,为避免消耗上述 Cloudflare worker 的额度限制,直接使用 Cloudflare 的 UDP DNS 服务
server 1.1.1.1 -group global-lite
server 1.0.0.1 -group global-lite
域名规则配置
我使用以下域名列表来区分不同类型的域名:
列表 | 说明 | 链接 |
---|---|---|
direct-list | 直连列表 | https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/direct-list.txt |
cn-apple-list | 中国大陆的 apple 域名列表,日常使用苹果设备比较多,单独处理下 | https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/apple-cn.txt |
cn-cdn-list | 国内 CDN 域名列表 | https://raw.githubusercontent.com/pmkol/easymosdns/main/rules/cdn_domain_list.txt |
proxy-list | 国外域名列表 | https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/proxy-list.txt |
gfw-list | 国外敏感域名列表 | https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/gfw.txt |
注意:下载的域名列表文件需要进行处理,以符合 SmartDNS 的规则格式:
- 将每行开头的
full:
替换为-.
- 删除每行开头的
domain:
- 遇到开头是
regexp:
的行,直接忽略
为确保 SmartDNS 的规则保持最新,可以编写定时任务定期更新这些列表文件,并重启 SmartDNS 服务使更新生效。
完整配置
SmartDNS 配置文件
log-level warn
bind :153
cache-file /etc/smartdns/smartdns.cache
cache-persist yes
cache-checkpoint-time 21600
prefetch-domain yes
force-qtype-SOA 65
force-AAAA-SOA yes
dualstack-ip-selection no
tcp-idle-time 300
server 223.5.5.5 -bootstrap-dns
# --- Direct Server 列表 --- #
# Aliyun
server 223.5.5.5 -group direct
# DNSPod
server 119.29.29.29 -group direct
# --- Proxy Server 列表 --- #
server-https https://xxxx.cloudflare-gateway.com/dns-query -group proxy
# --- global-lite Server 列表 --- #
server 1.1.1.1 -group global-lite
server 1.0.0.1 -group global-lite
# --- 域名配置列表 --- #
domain-set -t list -name direct-list -file /etc/smartdns/rules/direct-list.txt
domain-set -t list -name cn-apple-list -file /etc/smartdns/rules/cn-apple-list.txt
domain-set -t list -name cn-cdn-list -file /etc/smartdns/rules/cn-cdn-list.txt
domain-set -t list -name proxy-list -file /etc/smartdns/rules/proxy-list.txt
domain-set -t list -name gfw-list -file /etc/smartdns/rules/gfw-list.txt
# 本地域名只请求 direct,测速并使用最优结果
domain-rules /domain-set:cn-apple-list/ -nameserver direct
domain-rules /domain-set:cn-cdn-list/ -nameserver direct
domain-rules /domain-set:direct-list/ -nameserver direct
# 国外域名只请求 proxy,测速并使用最优结果
domain-rules /domain-set:proxy-list/ -nameserver proxy
# 国外敏感域名不要测速,只请求 proxy;注意顺序,放最后覆盖前面的配置
domain-rules /domain-set:gfw-list/ -nameserver proxy -speed-check-mode none
# 一些调用非常频繁的请求,直接用 global-lite
domain-rules /in-addr.arpa/ -nameserver direct
domain-rules /time.apple.com/ -nameserver global-lite
domain-rules /time.asia.apple.com/ -nameserver global-lite
domain-rules /pool.ntp.org/ -nameserver global-lite
domain-rules /time-ios.apple.com/ -nameserver global-lite
# 兜底:剩下的域名请求 proxy 与 direct,测速并使用最优结果
域名规则更新脚本
简单写了一个脚本用于每天拉取最新的规则,处理后如果发现有更新,就重启 SmartDNS
。简单配置在 crontab
中,每天更新一次。
#!/usr/bin/env python3
import os
import sys
import shutil
import requests
from datetime import datetime
from pathlib import Path
def log(msg):
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {msg}")
def process_url(url, filename):
script_dir = Path(__file__).parent.absolute()
rules_dir = script_dir / "rules"
rules_dir.mkdir(exist_ok=True)
log(f"Downloading URL: {url}")
try:
resp = requests.get(url)
resp.raise_for_status()
except requests.exceptions.RequestException as e:
log(f"Failed to download URL: {url} (Error: {str(e)})")
return False
log("Processing file content...")
processed_lines = []
for line in resp.text.splitlines():
if line.startswith("full:"):
processed_lines.append(line.replace("full:", "-."))
elif line.startswith("domain:"):
processed_lines.append(line.replace("domain:", ""))
elif line.startswith("regexp:"):
continue
else:
processed_lines.append(line)
if not processed_lines:
log("New file is empty. No update needed.")
return False
target_file = rules_dir / filename
new_content = "\n".join(processed_lines) + "\n"
if target_file.exists():
with open(target_file) as f:
old_content = f.read()
if old_content == new_content:
log("No differences found. No update needed.")
return False
log(f"{'Updating' if target_file.exists() else 'Creating'} file: {target_file}")
with open(target_file, "w") as f:
f.write(new_content)
return True
def main():
urls = [
("https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/direct-list.txt", "direct-list.txt"),
("https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/apple-cn.txt", "cn-apple-list.txt"),
("https://raw.githubusercontent.com/pmkol/easymosdns/main/rules/cdn_domain_list.txt", "cn-cdn-list.txt"),
("https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/proxy-list.txt", "proxy-list.txt"),
("https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/gfw.txt", "gfw-list.txt")
]
updated = False
for url, filename in urls:
if process_url(url, filename):
updated = True
print("-" * 18)
if updated:
log("Updates detected. Restart smartdns")
os.system("service smartdns restart")
else:
log("No updates detected.")
if __name__ == "__main__":
main()
总结
这套 DNS 配置方案经过实际使用,能够很好地满足我对家庭网络的需求:干净无广告、响应迅速、解析精准。通过组合使用 AdGuardHome 和 SmartDNS,既保证了广告过滤的效果,又能够智能选择最佳的 DNS 解析结果。
当然,每个人的网络环境和需求不同,可以根据自己的实际情况进行调整和优化。欢迎和我一起讨论~