在Ubuntu 24.04上使用nsd安裝一台Authoritative DNS Server

 我發現安裝Ubuntu 24.04 Server後預設會有systemd-resolved service在跑, 使用netstat -l指令查看, 會看到127.0.0.53之類的socket出現, 還有使用ls -l /etc/resolv.conf, 會發現這個檔案變成軟連結。問了Copilot, 它說: "127.0.0.53 是 Linux 系統(特別是使用 systemd 的發行版,如 Ubuntu)中 systemd-resolved 的本地 DNS stub resolver。它的作用是作為本機 DNS 中介,將應用程式的查詢轉發給實際的上游 DNS 伺服器。"而systemd-resolved的上遊是那台DNS server呢? 應該是放在 /etc/systemd/resolved.conf 這個設定檔, 這個檔可以如下設定:

[Resolve]

DNS=8.8.8.8
FallbackDNS=1.1.1.1

然後, 下指令:
sudo systemctl restart systemd-resolved

重啓systemd-resolved, 應該就可以正常的ping的到主機名稱了。

 問題是, 我要安裝nsd時, 會發現port 53已經被佔用, 不能安裝了。所以第一個動作, 我必須先禁用systemd-resolved, 改回使用原本的/etc/resolv.conf檔的老方法。Copilot告訴我的詳細作法:

-------------------------------------------------------------------------------------------------------
關閉 systemd-resolved 的完整步驟:
- 停止並禁用服務
sudo systemctl disable --now systemd-resolved
- 移除 /etc/resolv.conf 的符號連結(symbolic link)
預設這個檔案其實是連到 /run/systemd/resolve/stub-resolv.conf
sudo rm /etc/resolv.conf
- 建立一份你自己的 resolv.conf 檔案
你可以手動指定 DNS,例如使用 Google DNS:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
echo "nameserver 1.1.1.1" | sudo tee -a /etc/resolv.conf
- ✅ 確認你的設定生效
執行:
cat /etc/resolv.conf


- 確認內容是你剛剛設定的 DNS。
📌 提醒一下:
關掉 systemd-resolved 之後,你系統上的某些網路管理工具(如 NetworkManager)如果沒有特別設定,可能會重新覆蓋 /etc/resolv.conf。
-------------------------------------------------------------------------------------------------------

為了避免/etc/resolv.conf再被別的工具覆蓋, Copilot教的方法:

=============================================================
方法一:使用 chattr 鎖定 resolv.conf
這個方法簡單又有效,適合手動管理 DNS。
- 確保 resolv.conf 已存在並正確設定
cat /etc/resolv.conf
- 例如,內容應該類似:
nameserver 8.8.8.8
nameserver 1.1.1.1
- 鎖定該檔案以防修改
sudo chattr +i /etc/resolv.conf
- 這會把檔案設成不可修改(immutable)。
- 如果日後你想修改內容,請先移除鎖定:
sudo chattr -i /etc/resolv.conf
⚙️ 方法二:調整 NetworkManager 設定(如果你有用它)如果你的系統有安裝 NetworkManager,可以這樣讓它不要自動控制 DNS 設定。- 編輯設定檔:
sudo nano /etc/NetworkManager/NetworkManager.conf
- 在 [main] 區段底下加一行:
dns=none
- 重新啟動 NetworkManager:
sudo systemctl restart NetworkManager
- 然後再次手動建立 /etc/resolv.conf(就像你之前做的那樣)。
🧠 小叮嚀:使用 chattr +i 是最強制、也最不容易出錯的方法,但如果你未來會透過圖形介面或 DHCP 自動取得 DNS,那就建議使用方法二來保持彈性。
=============================================================

我自己因為只想安裝最單純的指令列Linux, 所以選擇將NetworkManager關掉:
# disable NetworkManager
sudo systemctl disable NetworkManager.service

到這裡就可以安裝nsd了。
sudo apt update
sudo apt upgrade
sudo apt install nsd

裝完, 可以設定nsd, 主要有2個設定檔:
sudo nano /etc/nsd/nsd.conf
sudo nano /var/lib/nsd/example.com.zone

設定檔如果都設定正確了, 可以啓動:
sudo systemctl start nsd

可以設定在開機時, 就啓動它:
sudo systemctl enable nsd

之後就可以使用dig, nslookup或者網路工具(如 dns checker)來檢查設定的對不對。

平時可以檢查nsd有沒有跑起來:
 systemctl list-units --type=service --state=running

**********************************************************************
*  錯誤訊息:  Cannot open /var/log/nsd.log for appending (Read-only file system)
**********************************************************************
我去問了Copilot, 它列了一些可能的問題點, 其中我覺得有用的是, 它說systemd sandbox 限制, 可以查看NSD 的 systemd 服務檔案,看它是否限制了寫入 /var/log?

特別注意以下幾個欄位是否啟用:
- ProtectSystem=full 或 strict:可能導致 /var/log 無法寫入
- ReadOnlyPaths=/var/log:明確將 /var/log 設為唯讀
- ReadWritePaths=:若有設定,應包含 /var/log 或你指定的 log 路徑

我下指令 sudo nano /lib/systemd/system/nsd.service 指令查看, 發現可疑的設定處:
ProtectSystem=strict
ReadWritePaths=/var/lib/nsd /etc/nsd /run

所以問題明顯地出在這裡了, 我做了修改:
ReadWritePaths=/var/lib/nsd /etc/nsd /run /var/log

存檔後, 下指令: 
sudo systemctl daemon-reexec
sudo systemctl restart nsd
sudo systemctl status nsd

$ sudo systemctl status nsd
● nsd.service - Name Server Daemon
     Loaded: loaded (/usr/lib/systemd/system/nsd.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-07-09 09:13:32 UTC; 57min ago
       Docs: man:nsd(8)
   Main PID: 4340 (nsd: xfrd)
      Tasks: 3 (limit: 1002)
     Memory: 38.1M (peak: 38.3M)
        CPU: 131ms
     CGroup: /system.slice/nsd.service
             ├─4340 /usr/sbin/nsd -d -P
             ├─4342 /usr/sbin/nsd -d -P
             └─4343 /usr/sbin/nsd -d -P

Jul 09 09:13:32 nserver systemd[1]: Starting nsd.service - Name Server Daemon...
Jul 09 09:13:32 nserver systemd[1]: Started nsd.service - Name Server Daemon.

果然, 錯誤訊息不見了。

也可以用
journalctl -u nsd
來查看log訊息。


留言

這個網誌中的熱門文章

D-BUS學習筆記

Cisco Switch學習筆記: EtherChannel

Cisco Switch學習筆記: interface的封包錯誤統計