如果家里、办公室或多台 VPS 上有很多设备,广告、跟踪域名和恶意跳转通常不是某一台电脑的问题,而是每台设备都在重复请求。AdGuard Home 把 DNS 过滤放到一个统一服务里:客户端先问它,再由它向上游 DNS 查询。
把 AdGuard Home 放到 VPS 上,可以让手机、电脑、家庭服务器和远程设备通过 WireGuard 或 Headscale 使用同一套 DNS 规则。它不需要在每台设备安装浏览器插件,也能统一做广告过滤、恶意域名拦截、本地 DNS 重写和查询日志。
不过,AdGuard Home 不是“装好就能公开提供的免费 DNS”。如果把公网 53 端口直接开放,VPS 很可能变成开放递归解析器,被滥用于放大攻击、扫描和流量转发。本文默认采用 VPN 私网接入、DNS 只监听私网 IP 的方案。
当前使用的官方稳定版是 AdGuard Home v0.107.78,Docker 持久化目录遵循官方镜像的 /opt/adguardhome/work 和 /opt/adguardhome/conf。
适合放在 VPS 的情况:
- 已经有 WireGuard、Tailscale 或 Headscale 私网;
- 想让远程手机、电脑和家庭设备使用同一套 DNS;
- 需要集中管理广告过滤、恶意域名和本地服务域名;
- 设备数量不大,查询量主要来自个人和家庭;
- 能接受维护 VPS、DNS、备份和访问策略。
不建议直接放到公网提供任意人使用的情况:
- 没有 VPN 或来源 IP 限制;
- 计划把 1.2.3.4:53 对全网开放;
- 不理解 DNS 递归、缓存、转发和放大攻击;
- 需要企业级审计、身份策略或大规模 Anycast DNS;
- 只想屏蔽浏览器广告,却不想维护一套网络服务。
如果只是家里几台设备,树莓派、NAS 或路由器也可以运行 AdGuard Home。VPS 的优势是远程可用、网络稳定、和 WireGuard/Headscale 容易组合;缺点是所有设备的 DNS 都依赖这台机器,必须准备备用 DNS 和恢复方案。
| 方案 | 主要能力 | 优点 | 注意点 |
|---|---|---|---|
| AdGuard Home | DNS 过滤、查询日志、重写、加密 DNS | 界面直观,支持 DoH/DoT 和多客户端 | 需要自己维护规则和隐私设置 |
| Pi-hole | DNS 过滤、列表和统计 | 社区成熟、资料很多 | 部分高级能力需要额外组件 |
| 公共 DNS | 直接递归查询 | 零维护、全球节点多 | 无法按家庭设备自定义过滤 |
| 浏览器广告拦截 | 只影响浏览器请求 | 安装简单、规则细 | 不处理 App、电视和 IoT 请求 |
AdGuard Home 适合“统一 DNS 策略”。它不会自动替代浏览器内容拦截器,也不能保证 YouTube、流媒体或所有 App 的广告都消失。DNS 只能拦截能够被域名层识别的请求。
假设 VPS 已经通过 WireGuard 建立私网:
VPS 公网 IPv4
│
├── WireGuard wg0: 10.66.66.1
│ │
│ ├── 手机: 10.66.66.2 ── DNS 53 ──┐
│ ├── 笔记本: 10.66.66.3 ─────────┤
│ └── 家庭服务器: 10.66.66.4 ────┤
│ ▼
└──────────── Docker AdGuard Home ── 上游 DoH/DoT DNS
这里的关键是:
- 客户端通过 WireGuard 加密连接到 VPS;
- AdGuard Home 的 53 端口只绑定 10.66.66.1,不绑定公网 IPv4;
- AdGuard Home 到上游 DNS 可以使用 DoH 或 DoT;
- 客户端不需要把管理后台暴露到公网。
如果还没有 WireGuard,可以先看 VPS 搭建 WireGuard VPN 教程。设备较多、需要标签和统一策略时,再看 VPS 搭建 Headscale 教程。
AdGuard Home 本身很轻,查询量不大的家庭场景可以从下面的配置开始:
| 场景 | 推荐配置 | 说明 |
|---|---|---|
| 个人和少量设备 | 1 核 1GB、20GB SSD | 日志保留时间不要设太长 |
| 家庭实验室 | 2 核 2GB、30GB SSD | 给 WireGuard、监控和缓存留余量 |
| 小团队或多站点 | 2–4 核、4GB+ | 重点评估查询量、备份和高可用 |
本文只需要这些端口:
- 53/tcp 和 53/udp:DNS 查询,只绑定 VPN 私网 IP;
- 3000/tcp:首次安装向导,只绑定 VPS 本机;
- 80/tcp:可选的 AdGuard Web 管理端口,只绑定本机或反向代理内部;
- 443/tcp、853/tcp:只有在明确配置 DoH/DoT 并限制访问时才开放。
先检查系统是否已经占用 53:
sudo ss -lntup | grep -E ':(53|3000|80|443|853)\b' || true
很多 Ubuntu 主机会运行 systemd-resolved,它通常监听 127.0.0.53:53。只要 AdGuard Home 绑定的是 WireGuard 私网地址 10.66.66.1,通常不会冲突;不要一看到 DNS 教程就盲目关闭 systemd-resolved。
如果你确实要让 AdGuard Home 监听 0.0.0.0:53,必须先理解本机解析器、Docker 端口和防火墙规则,否则可能让 VPS 自己无法解析域名,甚至暴露公网递归服务。
先确认 Docker 和 Compose 可用:
docker version
docker compose version
如果没有 Docker,可以参考 Docker 部署实战指南。创建 AdGuard Home 数据目录:
sudo mkdir -p /opt/adguardhome/work
sudo mkdir -p /opt/adguardhome/conf
sudo chown -R "$USER":"$USER" /opt/adguardhome
sudo chmod 750 /opt/adguardhome
确认 WireGuard 私网地址确实存在:
ip -4 addr show wg0
下面示例使用 10.66.66.1。如果你的接口地址不同,把 Compose 中所有 10.66.66.1 替换成实际地址。不要照抄一个不存在于本机的 IP,否则 Docker 绑定端口时会失败。
创建 /opt/adguardhome/compose.yaml:
services:
adguardhome:
image: adguard/adguardhome:v0.107.78
container_name: adguardhome
restart: unless-stopped
ports:
# 只在 WireGuard 私网 IP 提供 DNS,不绑定公网 IP
- "10.66.66.1:53:53/tcp"
- "10.66.66.1:53:53/udp"
# 首次安装和管理页面只通过 SSH 隧道访问
- "127.0.0.1:3000:3000/tcp"
- "127.0.0.1:8080:80/tcp"
volumes:
- /opt/adguardhome/work:/opt/adguardhome/work
- /opt/adguardhome/conf:/opt/adguardhome/conf
官方 Docker 示例还列出 DHCP、443、853 和 5443 等可选端口。本文不映射这些端口,因为 VPN 内的普通 DNS 已经由 WireGuard 加密,公开 DoH/DoT 不是默认必需项。
检查 Compose 文件:
cd /opt/adguardhome
docker compose config --quiet
启动容器:
docker compose up -d
docker compose ps
docker compose logs --tail=150 adguardhome
本机检查首次安装页面:
curl -I http://127.0.0.1:3000
如果报 bind: cannot assign requested address,先检查 wg0 是否启动、地址是否真的是 10.66.66.1。如果报端口已占用,再检查 ss 输出,不要直接换成公网端口解决。
在自己的电脑上建立隧道:
ssh -L 3000:127.0.0.1:3000 your_user@your_vps_ip
浏览器打开:
http://127.0.0.1:3000
初始化向导会让你设置管理员账号、Web 管理端口和 DNS 监听端口。建议:
- 管理员使用独立长密码,不与 VPS、邮箱和 VPN 复用;
- Web 管理端口保持容器内的 80,宿主机通过 127.0.0.1:8080 或 SSH 隧道访问;
- DNS 监听选择容器的所有接口,由宿主机端口映射限制到 10.66.66.1;
- 不启用不需要的 DHCP 服务,除非你明确知道 VPS 处于需要发放地址的二层网络;
- 记录你设置的 Web 管理地址,不要把管理员页面和 DNS 端口混为一谈。
完成向导后,管理页面在宿主机的本地端口 8080:
ssh -L 8080:127.0.0.1:8080 your_user@your_vps_ip
然后访问 http://127.0.0.1:8080。如果你更习惯使用第一次的 3000 隧道,也可以按向导显示的实际端口访问。
在 Settings → DNS settings 中配置上游服务器。可以选择 DoH 或 DoT,例如:
https://dns.cloudflare.com/dns-query
https://dns.google/dns-query
tls://1dot1dot1dot1.cloudflare-dns.com
再填写 Bootstrap DNS,例如:
1.1.1.1
9.9.9.9
Bootstrap DNS 只负责把上游域名解析成 IP,不等于所有客户端都会绕过 AdGuard Home。配置后用 Test upstreams 测试延迟和可用性。
几个实际建议:
- 先选 2 个稳定上游,不要堆十几个地址;
- 上游服务的隐私政策、日志周期和所在地区要自己确认;
- 需要稳定性时保留一个不同服务商的备用上游;
- DNSSEC、缓存和并发设置不要一次全部改动,方便定位问题;
- 上游 DoH/DoT 失败时,先看 VPS 时间、证书验证和 Bootstrap DNS。
客户端到 AdGuard Home 的 DNS 也可以使用 DoH/DoT,但如果客户端已经在 WireGuard 隧道里,普通 DNS 请求本身也被 VPN 加密,配置更简单、延迟通常更低。
在 Filters → DNS blocklists 中启用默认列表,再根据实际误拦截逐步增加规则。过滤列表不是越多越好:
- 多个列表高度重复,会增加内存和更新时间;
- 过于激进的列表可能破坏登录、支付和验证码;
- 列表 URL 失效时要及时移除;
- 更新后检查命中率和误拦截,不要只看“拦截数量”做优化。
遇到某个站点无法登录,先在 Query log 找到被拦截的域名,再添加单条允许规则。不要为了让一个页面恢复,就关闭所有过滤器。
常见规则操作:
- 允许某个域名:添加 @@||example.com^;
- 拦截某个域名:添加 ||ads.example.com^;
- 只对某个客户端生效:使用客户端关联的规则或设置;
- 需要临时验证:先暂停过滤一小段时间,确认后再恢复。
规则语法和第三方列表会变化,添加前先阅读来源说明。不要把来路不明的“万能规则包”直接复制到所有设备。
在客户端配置中把 DNS 指向 VPS 的 WireGuard 地址:
[Interface]
Address = 10.66.66.2/24
DNS = 10.66.66.1
服务端的 WireGuard 配置需要允许客户端访问 10.66.66.1/32 或对应私网段。先确认 VPN 能通,再测试 DNS:
ping 10.66.66.1
nslookup example.com 10.66.66.1
dig @10.66.66.1 example.com
如果 ping 通但 dig 不通,重点检查 Docker 端口映射、防火墙和 AdGuard Home 的监听状态。
可以把 AdGuard Home 的私网地址配置为统一 DNS,但要确认客户端的 MagicDNS、DNS 优先级和 exit node 规则没有覆盖它。Headscale 的 DNS 配置、ACL 和路由问题可以参考 VPS 搭建 Headscale 教程。
如果家庭路由器能通过 WireGuard 连接到 VPS,可以把 DHCP 下发的 DNS 指向家庭侧 VPN 地址。不同路由器对“所有客户端 DNS 强制走指定地址”的支持差异很大,先拿一台测试设备确认 nslookup 的服务器地址。
路由器本身可能把 IPv6 DNS 继续下发给客户端,导致部分查询绕过 AdGuard Home。启用 IPv6 时必须同时检查 RA、DHCPv6 和客户端的实际 DNS 列表。
在 Filters 或 Clients 中为设备设置名称和分组,例如:
- 家庭成员手机;
- 电视和游戏机;
- 家庭服务器;
- 工作设备;
- 临时访客。
客户端名称比单纯看 IP 更容易排查误拦截,但查询日志可能包含访问过的域名、时间和设备信息。建议:
- 缩短查询日志和统计保留时间;
- 不把日志公开给不需要的人;
- 备份配置前先评估日志是否包含隐私数据;
- 家庭成员共享时提前说明记录范围;
- 不用查询日志推断一个人的全部行为。
DNS rewrites 可以让私网服务使用稳定域名,例如:
grafana.home.example.com → 10.66.66.10
nas.home.example.com → 10.66.66.20
这样客户端无论在家里还是通过 VPN,都能使用同一套域名。注意:DNS 重写只改变解析结果,不会自动提供 HTTPS 证书。内网域名仍需要可信证书、应用配置或客户端信任链。
如果域名托管在 Cloudflare,不要为了私网解析把管理记录随意改成公网地址。可以使用单独的内网子域名,或者把重写规则限制在指定客户端。
先区分两种加密:
- AdGuard Home 到上游 DNS 的 DoH/DoT:保护 VPS 到上游解析器之间的查询;
- 客户端到 AdGuard Home 的 DoH/DoT:让浏览器或手机以加密协议访问你的 DNS。
第一种通常值得开启。第二种只有在客户端无法使用 VPN、网络会劫持 53 端口,或你确实需要 HTTPS/TLS DNS 时才考虑。
如果要提供客户端 DoH/DoT:
- 申请一个专用域名和有效证书;
- 只为受控设备提供访问,不做公开递归服务;
- 使用 NPM、Caddy、Cloudflare Access 或 VPN 限制来源;
- 对 /dns-query 和 853 端口设置连接数、流量和日志策略;
- 测试证书、SNI、IPv6 和移动网络的实际行为;
- 关闭不需要的管理 API 和 Web 页面公网入口。
对个人家庭场景,WireGuard + 普通 DNS 已经足够。不要为了“支持 DoH”把 53、443、853、3000、5443 一次全开放。
在客户端分别查看系统 DNS、VPN DNS 和浏览器的安全 DNS 设置。命令行可以这样测试:
dig @10.66.66.1 example.com
resolvectl status
你应该看到客户端把请求发到 10.66.66.1,而不是直接发往路由器、运营商 DNS 或浏览器内置 DoH。
如果浏览器开启了自己的 Secure DNS,它可能绕过系统 DNS。要么关闭浏览器独立 DoH,让所有请求走 AdGuard Home;要么明确配置浏览器使用你自己的 DoH,并接受它与系统 DNS 的策略不同。
AdGuard Home 的关键内容在两个目录:
- /opt/adguardhome/conf:配置、用户、监听和过滤设置;
- /opt/adguardhome/work:运行数据、过滤器缓存、统计和查询日志。
备份前暂停容器,减少写入过程中的不一致:
cd /opt/adguardhome
docker compose stop
sudo tar -czf adguardhome-$(date +%F).tar.gz work conf compose.yaml
docker compose start
把压缩包复制到另一台机器或对象存储,并限制权限:
chmod 600 adguardhome-*.tar.gz
如果不需要恢复查询日志,可以只备份 conf 和 Compose 文件。恢复前先停止容器,确认目录归属和版本兼容,再解压覆盖。
升级前记录当前版本并备份:
cd /opt/adguardhome
docker inspect adguardhome --format '{{.Config.Image}}'
docker compose config > compose.before-upgrade.yaml
然后修改镜像版本:
image: adguard/adguardhome:v0.107.78
拉取并重建:
docker compose pull
docker compose up -d
docker compose logs --tail=150 adguardhome
升级后测试:
- VPN 客户端能否解析域名;
- 过滤规则是否正常更新;
- 本地 DNS rewrites 是否仍生效;
- 上游 DoH/DoT 是否有错误;
- 查询日志和管理员登录是否正常。
如果出现回归,先停止容器,恢复备份,再把镜像改回之前的固定版本。不要只回退镜像而忽略配置格式变化。
Compose 绑定了 10.66.66.1,但宿主机当前没有这个地址。检查:
ip -4 addr show wg0
docker compose ps
确认 WireGuard 先启动,或者把 Compose 中的地址替换为实际私网 IP。不要改成 0.0.0.0 作为第一反应,那可能直接暴露公网 DNS。
查看进程:
sudo ss -lntup | grep ':53'
sudo lsof -nP -iTCP:53 -iUDP:53
常见占用者包括 systemd-resolved、dnsmasq、BIND、Unbound 和另一套容器。先决定哪个服务负责 DNS,再处理监听地址;不要同时运行两个默认监听所有地址的解析器。
按层测试:
ping 10.66.66.1
nc -vz 10.66.66.1 53
dig @10.66.66.1 example.com
docker exec adguardhome cat /opt/adguardhome/conf/AdGuardHome.yaml | sed -n '1,100p'
如果 ping 不通,先查 WireGuard 路由;如果 ping 通但 53 不通,查 Docker 映射和防火墙;如果 53 有响应但域名失败,再看上游 DNS 和过滤日志。
SERVFAIL 不等于“域名被拦截”。重点检查:
- 上游 DoH/DoT 的域名无法通过 Bootstrap DNS 解析;
- VPS 系统时间错误导致 TLS 验证失败;
- IPv6 上游可达性异常;
- DNSSEC 或上游服务临时故障;
- 过滤器误拦截了依赖域名。
先在 AdGuard Home 的 DNS settings 中测试上游,再用一个普通域名和一个已知被过滤域名分别验证。
打开 Query log,按客户端和时间筛选被拦截的请求。只添加必要的 allowlist 规则,验证后记录原因。不要把整个顶级域名加入白名单,除非你确认它只用于可信服务。
检查 VPS 磁盘、过滤器 URL、系统时间和出口网络:
df -h
docker compose logs --tail=200 adguardhome
缩短查询日志、统计和规则保留周期,删除失效列表。不要用无限增长的日志来判断服务是否健康。
检查路由器 RA、DHCPv6 和客户端的 DNS 列表:
resolvectl status
ip -6 route
如果客户端拿到了公共 IPv6 DNS,而 VPN 只配置了 IPv4 DNS,它可能优先使用 IPv6 绕过过滤。要么补齐 IPv6 VPN/DNS 配置,要么在路由器侧明确关闭错误的 IPv6 DNS 下发。
- 公网不开放递归 DNS 53,除非已经有严格来源控制和滥用监控;
- 53 只绑定 WireGuard、Tailscale 或其他私网地址;
- 3000、8080 等管理端口只监听回环地址或 VPN;
- 不启用不需要的 DHCP、DoT、DoH 和诊断端口;
- 管理员密码独立、足够长,不写进公开仓库;
- 查询日志和统计数据设置合理保留时间;
- 过滤列表只使用可信来源,定期检查误拦截;
- 配置目录和备份文件限制权限;
- 升级前固定版本并测试恢复;
- 为 DNS 服务配置健康检查和备用解析路径;
- 不把 AdGuard Home 当作防火墙、杀毒软件或完整家长控制系统;
- 只管理自己有权管理的设备和网络。
只要 DNS 端口绑定在 VPN 私网 IP,宿主机仍可使用 systemd-resolved 或其他本地解析器。不要把宿主机的 /etc/resolv.conf 直接改成一个还没有启动的 AdGuard Home 地址。
不能。它负责 DNS 查询和过滤,不负责传输层加密、路由、身份认证或访问控制。远程客户端仍需要 WireGuard、Tailscale、Headscale 或其他安全通道。
不一定。DoH/DoT 的主要价值是保护客户端到解析器的传输,额外的 TLS、HTTP 或连接复用可能改变延迟。VPN 内普通 DNS 已有加密隧道,应该用实际测速结果决定。
很多广告和业务内容使用同一域名,或者由 App 内置、加密和硬编码请求提供。DNS 层无法区分同域名下的不同路径,也不能替代应用层过滤。
个人和家庭场景可以从 1 核 1GB VPS、WireGuard 私网和 AdGuard Home v0.107.78 开始。先只接入一台测试手机,确认 VPN、DNS、过滤器、上游 DoH 和 IPv6 行为,再把其他设备切换过来。
不要把“拦截数量”当成唯一目标。真正稳定的 AdGuard Home 方案是:DNS 只对受控网络开放,规则数量适中,查询日志可控,有备用解析路径,配置和恢复步骤都写下来。
