快轉到主要內容

如何用Docker自架Unbound DNS伺服器

· 民國115年丙午年
·
切換繁體/簡體
分類 Linux系統 Self-hosting自架
標籤 DNS OpenBSD
目錄

我們知道有很多公共DNS伺服器可以用,那麼你有沒有想過自己架設一個呢?從今天起透過「Unbound」實施DNS自主吧!

為什麼要自架一個DNS伺服器:我們可以把DNS想像成網際網路的門牌。當你輸入一個網址時,就像在找房子地址。但電腦其實不知道這個名字對應哪一個IP位址,就像只知道人名,卻不知道門牌號碼一樣。此時,DNS伺服器就像是一個幫你查門牌的查號台。當你第一次查詢網站時,它會幫你找到正確的IP位址,用DNS快取把結果記在附近,讓下一次查詢可以更快完成。不過呢,DNS伺服器如果是使用公共的,你等於是直接問現有查號台,而非自己去找地址。那麼,負責回答你問題的DNS伺服器就很關鍵了,它能夠干涉你所能看到的網站。要是…它回覆的內容不誠實呢?因為各種因素,過濾掉了你不該看到的東西,或者導向錯誤的地址。那麼這時,自己架設一個DNS伺服器便有必要了。

「Unbound」是一種自架DNS伺服器的方案,由NLnet Labst開發。

你可以在離你家電腦最近的伺服器用Unbound,建立DNS快取,加快造訪網站時的網路回應速度,減少延遲。並且查詢DNS位址的時候會啟用DNS over TLS,防止網路業者(ISP)窺探你造訪的網站為何,保護隱私。

Unbound屬於Recursive DNS Resolver。跟Pi-hole和AdGaurd Home不同,Unbound本身沒有擋廣告的功能,就只是一個DNS伺服器,目的是為了解析網域,給你一個中立無審查的網路。不過你也可以將Unbound搭配Pi-hole一起用。

Unbound可以部署在家裡的NAS,當作私人的DNS使用,也可以放在VPS給大眾存取。

順帶一提,Unbound是使用BSD三句版授權釋出的自由軟體,並且是OpenBSD系統預設使用的DNS Resolver喔!

1. Forwarding與Recursive的差別?
#

Unbound查詢DNS的時候可以分為「Forwarding Resolver」與「Recursive Resolver」模式。

Forwarding Resolver,轉送解析器,只是將DNS查詢轉交給上游的大型DNS伺服器(如Google、Quad9、Cloudflare)並返回IP位址。利用他們一天幾十萬上下快取好的DNS資料加速查詢。但是你就得慎選上游的DNS伺服器了,因為有的DNS伺服器會「為了你好」而過濾掉一些網站,導致你得到不中立的結果。

Recursive Resolver,遞迴解析器,則是完全自立自強,從查詢Root DNS Server、Top Level Domain Server、Authoritative DNS Server都跑一遍。逐層查詢IP位址。不依賴大型DNS伺服器。查詢過的DNS資料會快取下來,增加下次載入速度。

我這篇文章是 採用Recursive Resolver的架構

2. 確認一下伺服器的DNS架構
#

首先要確認伺服器沒有其他干擾因素再安裝Unbound。

測試系統:Ubuntu 24.04

  1. Ubuntu 24.04以後版本的系統,應該是NetworkManager在管網路。也有可能會加上systemd-resolved來處理DNS。如下查詢服務狀態:
sudo systemctl status NetworkManager

sudo systemctl status systemd-resolved
  1. Unbound DNS伺服器需要使用53通訊埠,用ss指令確保它沒被任何行程佔用。建議不要修改通訊埠,因為一些軟體不支援自訂DNS的通訊埠。
sudo ss -lntup | grep :53
  1. 如果伺服器有使用systemd-resolved,而且監聽53通訊埠的話,將其關掉
sudo vim /etc/systemd/resolved.conf
  1. 改成DNSStubListener=No
[Resolve]
DNSStubListener=no
  1. 執行resolvectl確認伺服器沒有使用其他DNS。
sudo resolvectl
  1. 查看伺服器IP,例如我這臺區域網路的機器IP是192.168.1.116
ip addr

3. 建立docker-compose
#

Unbound可以用多種方式部署。根據Unbound官網資料,目前沒有官方Docker映像檔。

我選用klutchell打包的unbound-docker映像檔,支援x86與ARM架構。內含DNSSEC需要的信任錨點root.key與Root DNS Server列表root.hints所以你不用手動下載。

  1. 建立存放資料的目錄
mkdir -p ~/unbound

cd ~/unbound
  1. 建立Unbound設定檔
vim unbound.conf
  1. 填入以下內容
server:
  verbosity: 1

  interface: 0.0.0.0
  port: 53

  do-ip4: yes
  do-udp: yes
  do-tcp: yes
  do-ip6: yes

  # 若是架在區域網路,應只允許區域內電腦IP連線
  access-control: 127.0.0.0/8 allow
  access-control: 192.168.0.0/16 allow
  access-control: 10.0.0.0/8 allow
  access-control: 0.0.0.0/0 refuse

  # 查詢時不回傳Unbound版本,只回傳必要資訊,增強隱私
  hide-identity: yes
  hide-version: yes
  qname-minimisation: yes

  # 自動更新DNS快取
  prefetch: yes
  prefetch-key: yes

  # 設定DNS快取存活時間
  cache-min-ttl: 0
  cache-max-ttl: 86400
  1. 建立docker-compose.yml
vim docker-compose.yml
  1. 填入:
services:
  unbound:
    image: klutchell/unbound
    container_name: unbound
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./unbound.conf:/etc/unbound/custom.conf.d/unbound.conf
  1. 啟動:
docker compose up -d
  1. 開放防火牆通訊埠:
sudo ufw allow 53

sudo ufw reload

4. 修改裝置DNS指向Unbound伺服器
#

Android手機
#

設定 → 私人DNS。Android強制要求有網域才能用。

若只有區域IP,則是在Wifi界面設定,將DHCP改為靜態,裡面就可以填寫IP了。

Linux電腦客戶端
#

  1. Ubuntu 24.04如果使用systemd-resolved的話,用NetworkManager改不夠,可能還要改systemd-resolved設定。

  2. 看看目前使用的網路界面,例如這裡使用有線網路為enp2s0

sudo nmcli connection show --active

sudo resolvectl status
  1. 修改如下
sudo resolvectl dns enp2s0 "192.168.1.116"

sudo resolvectl domain enp2s0 "~."
  1. 再用nmcli修改目前連線的DNS伺服器
sudo nmcli connection show --active

sudo nmcli con mod "連線名稱" ipv4.dns "192.168.1.116"

5. 測試Unbound DNS有無啟用成功
#

  1. 在Linux電腦客戶端安裝DNS測試工具
sudo apt install bind9-dnsutils
  1. 執行dig指令,使用Unbound(這裡IP是192.168.1.116)去查詢網站,看是否會經過Unbound。
dig @192.168.1.116 google.com
  1. 成功的話,SERVER應該顯示192.168.1.116

  2. 另外查詢過一次該域名的話,Unbound就會快取在伺服器。因此再執行一次dig指令的話,Query time應會變低或降至零。

相關文章


此處提供二種留言板。點選按鈕,選擇您覺得方便的留言板。

(留言板載入中)這是Giscus留言板,需要Github帳號才能留言。支援Markdown語法,若要上傳圖片請善用外部圖床。您的留言會在Github Discussions向所有人公開。

Click here to edit your comments.

(留言板載入中)這是Disqus留言板,您可能會看到Disqus強制投放的廣告。您可以匿名留言。為防止垃圾內容,有時留言可能會被系統判定需審核,導致延遲顯示,請見諒。若要上傳圖片請善用外部圖床網站。