====== 安裝 Pi-hole+Unbound 的 DNS (Docker) ====== * 因為之前安裝 Bind 的 DNS 管理成本很高, 最近上網廣告很多, 想直接透過 DNS 來阻絕廣告, 剛好看到這個 [[https://pi-hole.net/|Pi-hole]] + [[https://nlnetlabs.nl/projects/unbound/about/|Unbound]] 的方案 * 安裝環境 : * VM : 1vCore, 1G RAM, 16G SSD * OS : Alpine 3.21 + Docker Compose * 參考 [[tech/alpine_docker]] ===== 安裝設定 ===== * 編輯 docker-compose.yml networks: dns_net: driver: bridge ipam: config: - subnet: 172.22.0.0/16 external: false services: pihole: container_name: pihole hostname: pihole image: pihole/pihole:latest #shm_size: '2gb' networks: dns_net: ipv4_address: 172.22.0.6 ports: - "53:53/tcp" - "53:53/udp" - "8080:80/tcp" environment: - 'TZ=Asia/Taipei' - 'WEBPASSWORD=mypassword' - 'DNS1=172.22.0.7#53' - 'DNS2=1.1.1.1' - 'DNSSEC=true' - 'REV_SERVER=true' - 'REV_SERVER_DOMAIN=local' - 'REV_SERVER_TARGET=172.22.0.1' - 'REV_SERVER_CIDR=172.22.0.0/16' cap_add: - NET_ADMIN - SYS_NICE volumes: - './etc-pihole/:/etc/pihole/' - './etc-dnsmasq.d/:/etc/dnsmasq.d/' - '/etc/resolv.conf:/etc/resolv.conf:ro' depends_on: unbound: condition: service_healthy healthcheck: test: ["CMD", "dig", "@127.0.0.1", "-p53", "pi.hole"] interval: 30s timeout: 10s retries: 3 start_period: 10s #disable: true restart: unless-stopped unbound: container_name: unbound image: mvance/unbound:latest networks: dns_net: ipv4_address: 172.22.0.7 volumes: #- ./etc-unbound:/opt/unbound/etc/unbound - ./etc-unbound/root.hints:/opt/unbound/etc/unbound/root.hints:ro ports: - "5053:53/tcp" - "5053:53/udp" healthcheck: disable: false restart: unless-stopped * 啟動服務 docker compose up -d ===== 開始使用 ===== * Pi-hole 管理網址 - http://hostip:8080/admin (使用 mypassword 登入) \\ {{:tech:2023-11-02_021124.png?600|}} \\ {{:tech:2023-11-02_021218.png?600|}} * 確認設定使用 unbound - 172.22.0.7#53 \\ {{:tech:2023-11-02_021355.png?600|}} ===== 驗證成效 ===== * 使用 https://d3ward.github.io/toolz/adblock.html 進行驗證 \\ {{:tech:2023-11-02_120722.png?600|}} * 可以參考 https://firebog.net/ 加入 ADList 提高阻擋廣告的能力 \\ {{:tech:2023-11-03_103014_1.png?600|}} * 可以參考 https://github.com/sefinek24/Sefinek-Blocklist-Collection/blob/main/lists/md/Pi-hole.md 加入 ADList 提高阻擋廣告能力 * 可以參考 [[tech/dnsperf]] ===== FAQ ===== - unbound 預設阻擋上游 DNS 回復私有網路保留 IP 網段 Exp. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 , 如果要開放這限制, 需要 - 複製 unbound 內的 /opt/unbound/etc/unbound 目錄出來成為 etc-ubound docker cp unbound:/opt/unbound/etc/unbound . mv unbound etc-unbound - 修改 docker-compose.yml 將 volumes 註記取消, 讓 etc-ubound 可掛載起來 : unbound: container_name: unbound image: mvance/unbound:latest networks: dns_net: ipv4_address: 172.22.0.7 volumes: - ./etc-unbound:/opt/unbound/etc/unbound ports: : - 修改 ./etc-unbound/unbound.conf 將 private-address 設定註記掉 Exp. : # These private network addresses are not allowed to be returned for public # private-address: 10.0.0.0/8 # private-address: 172.16.0.0/12 # private-address: 192.168.0.0/16 # private-address: 169.254.0.0/16 # private-address: fd00::/8 # private-address: fe80::/10 # private-address: ::ffff:0:0/96 : - 重新啟動 docker compose docker compose up -d - 如何調整自動更新週期 * 參考 : * [[https://discourse.pi-hole.net/t/auto-update-gravity-database/60375|將 /etc/cron.d/pihole 掛載出來]] **此方式會造成重啟時, dnsmasq 無法正常啟動**:-? * [[https://github.com/pi-hole/docker-pi-hole/issues/107|在 host 使用 docker exec 執行更新]] - 先確認可以在 host 執行更新 docker exec pihole pihole updateGravity - 在 host 建立 crontab 定義更新週期 - 如何增加一筆 wildcard 的 DNS 紀錄 Exp. *.lab.ichiayi.com -> 192.168.11.30 * 參考網址 - https://hetzbiz.cloud/2022/03/04/wildcard-dns-in-pihole/ * 參考網址 - https://www.reddit.com/r/pihole/comments/1it0xm8/wildcard_dns_in_pihole_v6/?rdt=47952 * 其實是可以設定, 只是無法直接透過 GUI 來處理 * 在 pi-hole v6 之後, 需要再 GUI 勾選 **misc.etc_dnsmasq_d** * Settings->All settings->Miscellaneous->**[√]misc.etc_dnsmasq_d** * 手動處理程序如下: - 在 /etc/dnsmasq.d/ 目錄, 也就是對應出來的 /etc-dnsmasq.d 目錄內建立一個檔案 Exp. 02-lab-wildcard-dns.conf - 在檔案內加入 address=/lab.ichiayi.com/192.168.11.30 - 重啟 pihole-FTL 服務 docker compose restart pihole - 透過 nslookup abc.lab.ichiayi.com 就可以看到回應的 IP 是 192.168.11.30 - 如何增加一筆 MX 的 DNS 紀錄 Exp. mail.ichiayi.com -> mail.ichiayi.com , 50 * 參考網址 - https://github.com/imp/dnsmasq/blob/master/dnsmasq.conf.example * 其實是可以設定, 只是無法透過 GUI 來處理. 手動處理程序如下: - 在 /etc/dnsmasq.d/ 目錄, 也就是對應出來的 /etc-dnsmasq.d 目錄內建立一個檔案 Exp. 03-mail.conf - 在檔案內加入 mx-host=mail.ichiayi.com,mail.ichiayi.com,50 - 重啟 pihole-FTL 服務 docker compose restart pihole - 透過 nslookup set type=mx mail.ichiayi.com 就可以看到回應 - 當發現 pi-hole 內的 nslookup 查詢速度很緩慢(/etc/resolv.conf -> nameserver 127.0.0.11) * 參考 - https://stackoverflow.com/questions/64007727/docker-compose-internal-dns-server-127-0-0-11-connection-refused - 將 docker-compose.yml 內的 : ports: - 53:53/udp - 53:53/tcp : 前面加上 host ip Exp. 172.16.0.245 : ports: - 172.16.0.245:53:53/udp - 172.16.0.245:53:53/tcp : - 重啟 docker compse 即可解決 - 當大量查詢 pi-hole DNS 服務, 結果出現 FTL is not running 異常狀況 * 參考網址 - https://github.com/pi-hole/docker-pi-hole/issues/571 * docker compose logs -f 持續出現 Stopping pihole-FTL 的訊息 * docker exec pihole df -h | grep shm 出現 100% 表示 Share Memory 已經被大量 query 的紀錄塞爆 * 可以透過修改 docker-compose.yml 內將 shm_size(預設是 64MB)加大來解決, 但注意要確認不能超過主機記憶體大小 - 將 docker-compose.yml 內 #shm_size='2gb' 的 # 移除, 後面 2gb 可以改成實體主機記憶體大小的 70% 左右 - 重新啟動 docker compose docker compose up -d - 確認修改是否成功 pve-dns:~# docker exec pihole df -h | grep shm shm 2.0G 65M 2.0G 4% /dev/shm - 當設定 LocalDNS 後查詢還會取用到外部 DNS 回傳的 IPv6 的 IP 問題的解法 * 參考 - https://github.com/pi-hole/pi-hole/issues/5158 - 當 pi-hole diagnosis 出現 Maximum number of concurrent DNS queries reached (max: 150) 這警告訊息 * 先查看發生時間時段 /var/log/pihole/pihole.log 的紀錄內容 * 如果確認有 Client 會正常大量查詢 DNS Exp. 監控系統 可以先將 Rate-limiting 調大 * 在 Settings->DNS->Advanced DNS settings->Rate-limiting 修改 Exp. \\ {{:tech:螢幕擷取畫面_2024-05-18_094245.png?600|}} * 如果是出現大量內部 IP 反查紀錄 Exp. query[PTR] 51.173.43.10.in-addr.arpa from 10.20.2.218 可試著設定不要回覆私有 IP 的反查 * 在 Settings->DNS->Advanced DNS settings->Never forward reverse lookups for private IP ranges 打勾 \\ {{:tech:螢幕擷取畫面_2024-05-18_103208.png?600|}} ===== 參考網址 ===== * https://discourse.pi-hole.net/t/pihole-unbound-in-docker/62121 * https://hub.docker.com/r/mvance/unbound * https://hub.docker.com/r/pihole/pihole {{tag>dns adblock}}