Homelab Pi-hole DNS (家庭实验室 Pi-hole DNS)
Pi-hole 是一个网络范围的 DNS 广告拦截器,运行于树莓派或任何 Linux 主机上。 网络上所有设备都会自动获得广告和恶意域名拦截——无需浏览器扩展。
何时使用
- 在树莓派或 Linux 主机上安装 Pi-hole
- 将 Pi-hole 配置为家庭网络的 DNS 服务器
- 添加或管理广告列表
- 设置 DNS-over-HTTPS (DoH) 上游解析器
- 创建本地 DNS 记录(例如:
nas.home.lan、pi.home.lan) - 排查安装 Pi-hole 后设备无法访问互联网的问题
- 运行 Pi-hole 以替代或配合 DHCP
Pi-hole 工作原理
正常流程(无 Pi-hole):
设备 → 请求 ads.tracker.com → ISP DNS → 真实 IP → 广告加载
使用 Pi-hole:
设备 → 请求 ads.tracker.com → Pi-hole DNS → 被拦截(返回 0.0.0.0)→ 无广告
所有 DNS 查询首先经过 Pi-hole。
Pi-hole 会对照广告列表进行检查。
被拦截的域名返回空响应——广告/跟踪器永远不会加载。
允许的域名会被转发到您的上游解析器(Cloudflare、Google 等)。
安装
Docker(推荐)
Docker 是安装 Pi-hole 最简单的方式,并且可以方便地进行更新和备份。
# docker-compose.yml
services:
pihole:
image: pihole/pihole:<pinned-release-tag>
container_name: pihole
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp" # Web 管理界面
environment:
TZ: "America/New_York"
WEBPASSWORD: "${PIHOLE_WEBPASSWORD}" # 通过 .env 文件或密钥设置
PIHOLE_DNS_: "1.1.1.1;1.0.0.1"
DNSMASQ_LISTENING: "all"
volumes:
- "./etc-pihole:/etc/pihole"
- "./etc-dnsmasq.d:/etc/dnsmasq.d"
restart: unless-stopped
cap_add:
- NET_ADMIN # 仅当 Pi-hole 将提供 DHCP 服务时需要
在部署前,将 <pinned-release-tag> 替换为当前的 Pi-hole 发布标签。
对于长期运行的 DNS 基础设施,应避免使用 latest,以便升级过程是可管理和可审核的。
在 docker-compose.yml 旁边设置 PIHOLE_WEBPASSWORD 于 .env 文件中,将其 chmod 为 600,并确保不提交到 Git——切勿将密码直接放在 Compose 文件中。
访问 Web 管理界面:http://<pi-ip>/admin
裸机安装(Raspberry Pi OS / Debian / Ubuntu)
Pi-hole 在安装前需要一个静态 IP 地址。
# 步骤 1:分配静态 IP(在 Pi OS 上编辑 /etc/dhcpcd.conf)
sudo nano /etc/dhcpcd.conf
# 在末尾添加:
interface eth0
static ip_address=192.168.3.2/24
static routers=192.168.3.1
static domain_name_servers=192.168.3.1
# 步骤 2:在运行安装程序前下载并检查它。
# 优先使用 Pi-hole 为您的操作系统/版本记录的软件包或安装程序路径。
curl -sSL https://install.pi-hole.net -o pi-hole-install.sh
less pi-hole-install.sh # 在继续之前审核
# 步骤 3:运行
bash pi-hole-install.sh
# 按照交互式安装程序的引导:
# 1. 选择网络接口(推荐使用有线接口 eth0)
# 2. 选择上游 DNS(Cloudflare 或保持默认——以后可更改)
# 3. 确认静态 IP
# 4. 安装 Web 管理界面(推荐)
# 5. 记下最后显示的管理员密码
将您的网络指向 Pi-hole
# 方法 1:在路由器 DHCP 设置中更改 DNS(推荐)
路由器管理界面 → DHCP 设置 → DNS 服务器
主 DNS:192.168.3.2(Pi-hole IP)
辅助 DNS:留空以进行严格拦截,或使用第二个 Pi-hole。
在部署期间,公共备用 DNS(如 1.1.1.1)可以提高可用性,但客户端可能会绕过拦截直接查询它。
所有设备在下一次 DHCP 续约时自动以 Pi-hole 作为 DNS。
强制续约:重新连接 Wi-Fi 或在 Linux 上运行 'sudo dhclient -r && sudo dhclient'
# 方法 2:单设备 DNS(在全面推广前进行测试时有用)
Windows:控制面板 → 网络适配器 → IPv4 属性 → 手动设置 DNS
macOS:系统设置 → 网络 → 详情 → DNS → 手动设置
Linux:/etc/resolv.conf 或 NetworkManager
# 方法 3:Pi-hole 作为 DHCP 服务器(替代路由器 DHCP)
Pi-hole 管理界面 → 设置 → DHCP → 启用
首先在路由器上禁用 DHCP——同一网络上两个 DHCP 服务器会造成冲突
优点:主机名解析自动生效(设备会注册自己的名称)
广告列表管理
# Pi-hole 管理界面 → 广告列表 → 添加新的广告列表
# 推荐的广告列表:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
# 默认——超过 20 万个域名
https://blocklistproject.github.io/Lists/malware.txt
# 恶意软件域名
https://blocklistproject.github.io/Lists/tracking.txt
# 跟踪/遥测域名
# 添加列表后:
工具 → 更新 Gravity(下载并编译所有广告列表)
# 如果某个本不该被拦截的网站被拦截了(误报):
Pi-hole 管理界面 → 白名单 → 添加域名
示例:api.my-legitimate-service.com
# 实时查看被拦截的内容:
仪表盘 → 查询日志(实时 DNS 查询流,显示拦截/允许状态)
DNS-over-HTTPS 上游
DNS-over-HTTPS 会加密您的 DNS 查询,使您的 ISP 无法看到您解析了哪些网站。
# 安装 cloudflared(Cloudflare 的 DoH 代理)。
# 优先使用 Cloudflare 的软件包仓库以进行自动签名包验证。
# 如果您直接下载二进制文件,请固定一个发布版本并验证其校验和。
CLOUDFLARED_VERSION="<pinned-version>"
curl -LO "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-arm64"
# 在安装前从 Cloudflare 的发布说明中验证校验和/签名。
sudo mv cloudflared-linux-arm64 /usr/local/bin/cloudflared
sudo chmod +x /usr/local/bin/cloudflared
# 创建 cloudflared 配置
sudo mkdir -p /etc/cloudflared
sudo tee /etc/cloudflared/config.yml << EOF
proxy-dns: true
proxy-dns-port: 5053
proxy-dns-upstream:
- https://1.1.1.1/dns-query
- https://1.0.0.1/dns-query
EOF
# 创建 systemd 服务
sudo cloudflared service install
sudo systemctl start cloudflared
sudo systemctl enable cloudflared
# 现在将 Pi-hole 指向本地 DoH 代理:
# Pi-hole 管理界面 → 设置 → DNS → 自定义上游 DNS
# 设置为:127.0.0.1#5053
# 取消选中所有其他上游解析器
本地 DNS 记录
让您的服务可以通过名称访问(例如:nas.home.lan、grafana.home.lan)。
域名说明:
.home.lan在家庭实验室中广泛使用且实际可用。 IETF 为本地使用保留的后缀是.home.arpa(RFC 8375)——使用该后缀以遵循标准。 对于 Pi-hole DNS 记录,避免使用.local,因为它会与 mDNS/Bonjour 冲突。
# Pi-hole 管理界面 → 本地 DNS → DNS 记录
域名 IP
nas.home.lan 192.168.30.10
pi.home.lan 192.168.30.2
grafana.home.lan 192.168.30.3
proxmox.home.lan 192.168.30.4
# 从网络上的任何设备:
ping nas.home.lan → 192.168.30.10
http://grafana.home.lan → 您的 Grafana 仪表盘
# 对于子域名,添加 CNAME 记录:
Pi-hole 管理界面 → 本地 DNS → CNAME 记录
域名:portainer.home.lan → 目标:pi.home.lan
故障排除
# Pi-hole 拦截了本不该拦截的内容
pihole -q example.com # 检查域名是否被拦截以及由哪个列表拦截
pihole -w example.com # 立即加入白名单
# DNS 根本无法解析
pihole status # 检查 pihole-FTL 是否在运行
dig @192.168.3.2 google.com # 直接对 Pi-hole 测试 DNS
# 重启 Pi-hole DNS
pihole restartdns
# 检查特定设备的查询日志
pihole -t # 实时输出所有查询
# 或者通过 Web 管理界面查询日志按客户端过滤
# Pi-hole gravity 更新(刷新广告列表)
pihole -g
反模式
# 错误:依赖单个 Pi-hole 且没有恢复路径
# 如果 Pi-hole 崩溃或 Pi 断电,DNS 可能会停止工作
# 正确:在设置期间保留一份记录的 router 回退方案
# 更好:运行两个 Pi-hole 实例以实现冗余;对于严格拦截,避免使用公共备用 DNS
# 错误:在未设置静态 IP 的情况下安装 Pi-hole
# 如果 Pi 获得新的 DHCP IP,所有设备都会失去 DNS
# 正确:先设置静态 IP,再安装 Pi-hole
# 错误:在未先禁用路由器 DHCP 的情况下启用 Pi-hole DHCP
# 同一网络上的两个 DHCP 服务器会分配冲突的 IP
# 正确:先禁用路由器 DHCP,再启用 Pi-hole DHCP
# 错误:从不更新 gravity(广告列表)
# 新的广告和恶意域名会不断出现——过期的列表会遗漏它们
# 正确:安排每周的 gravity 更新:pihole -g(或在设置 → API 中启用)
最佳实践
- 在安装 Pi-hole 之前,为 Pi 分配静态 IP 或 DHCP 预留
- 使用 Pi-hole 作为主 DNS;如果需要严格拦截,为了冗余,添加第二个 Pi-hole 而非公共解析器
- 使用 cloudflared 启用 DoH(DNS-over-HTTPS)以实现加密的上游查询
- 将
home.lan设置为您的本地域名,并为所有服务创建 DNS 记录 - 偶尔查看查询日志——被拦截的查询会显示您的设备正在做什么
相关技能
- homelab-network-setup
- homelab-vlan-segmentation
- homelab-wireguard-vpn