家庭实验室 Pi-hole DNS 是做什么的?
Pi-hole 是一个网络级的 DNS 广告拦截器,可在 Raspberry Pi 或任何 Linux 主机上运行。 你网络上的所有设备都能自动获得广告和恶意软件域名拦截——无需浏览器扩展。
何时使用
- 在 Raspberry Pi 或 Linux 主机上安装 Pi-hole
- 将 Pi-hole 配置为家庭网络的 DNS 服务器
- 添加或管理阻止列表
- 设置 DNS-over-HTTPS (DoH) 上游解析器
- 创建本地 DNS 记录(例如
nas.home.lan、pi.home.lan) - 排查安装 Pi-hole 后设备失去互联网连接的问题
- 让 Pi-hole 与 DHCP 一起运行,或替代 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:<固定版本标签>
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 时需要
在部署前将 <固定版本标签> 替换为当前的 Pi-hole 版本标签。
对于长期运行的 DNS 基础设施,避免使用 latest,以便升级是经过慎重考虑和可审查的。
在 docker-compose.yml 同级目录下的 .env 文件中设置 PIHOLE_WEBPASSWORD,将其权限设为 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 管理界面 → Adlists → 添加新的阻止列表
# 推荐的阻止列表:
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="<固定版本>"
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 可能停止工作
# 正确:在设置过程中保留一个文档化的路由器回退方案
# 更好:运行两个 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