自架實驗室 Pi-hole DNS
Pi-hole 是一個運行於 Raspberry Pi 或任何 Linux 主機上的網路層級廣告封鎖器。 網路上所有裝置都會自動獲得廣告與惡意軟體網域封鎖功能,無需安裝瀏覽器擴充功能。
使用時機
- 在 Raspberry Pi 或 Linux 主機上安裝 Pi-hole
- 將 Pi-hole 設定為家庭網路的 DNS 伺服器
- 新增或管理封鎖清單
- 設定 DNS-over-HTTPS (DoH) 上游解析器
- 建立區域 DNS 記錄(例如
nas.home.lan、pi.home.lan) - 排除安裝 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" # 網頁管理介面
environment:
TZ: "America/New_York"
WEBPASSWORD: "${PIHOLE_WEBPASSWORD}" # 透過 .env 檔案或 secret 設定
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 檔案中。
存取網頁管理介面: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. 安裝網頁管理介面(建議)
# 5. 記下結尾顯示的管理員密碼
將網路指向 Pi-hole
# 方法 1:在路由器 DHCP 設定中變更 DNS(建議)
路由器管理 UI → DHCP 設定 → DNS 伺服器
主要 DNS:192.168.3.2(Pi-hole IP)
次要 DNS:為了嚴格封鎖請留空,或者使用第二台 Pi-hole。
在佈署期間,使用像 1.1.1.1 這樣的公開備援 DNS 可提高可用性,
但可能因為用戶端會查詢它而繞過封鎖。
所有裝置會在下次 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 → 新增 adlist
# 推薦的封鎖清單:
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 # 即時查看所有查詢
# 或在網頁管理介面的查詢記錄中依用戶端篩選
# Pi-hole gravity 更新(重新整理封鎖清單)
pihole -g
反模式
# 錯誤:僅依賴單一 Pi-hole 而沒有復原路徑
# 如果 Pi-hole 當機或 Raspberry Pi 斷電,DNS 可能會停止運作
# 正確:在設定過程中保留一個可記錄的路由器備援方案
# 更佳:運行兩個 Pi-hole 實例以實現備援;如需嚴格封鎖,請避免使用公開備援 DNS
# 錯誤:在沒有靜態 IP 的情況下安裝 Pi-hole
# 如果 Raspberry Pi 取得新的 DHCP IP,所有裝置都會失去 DNS
# 正確:先設定靜態 IP,再安裝 Pi-hole
# 錯誤:在沒有先停用路由器 DHCP 的情況下啟用 Pi-hole DHCP
# 網路上有兩個 DHCP 伺服器會分配衝突的 IP
# 正確:停用路由器 DHCP,然後啟用 Pi-hole DHCP
# 錯誤:從不更新 gravity(封鎖清單)
# 新的廣告和惡意軟體網域會不斷累積——過時的清單會漏掉它們
# 正確:安排每週更新 gravity:pihole -g(或在設定 → API 中啟用)
最佳實務
- 在安裝 Pi-hole 前,為 Raspberry 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