實體主機 DNS 解析異常:逐層確認查詢路徑
業務程序回報網域名稱解析失敗,但直接透過位址存取仍然正常時,立即更換 DNS 伺服器往往會掩蓋故障現場。問題可能出在應用程式快取、NSS 查詢順序或系統解析服務,也可能是上游回傳了錯誤。排查的目標不是讓某個指令偶爾成功,而是確認業務程序實際走哪條解析路徑,以及錯誤發生在哪一層。
本文以 Ubuntu Server 24.04 LTS 為操作環境。AMDSSH 實體主機付款後,可在控制台查看登入憑證,再透過 SSH 登入;主機有多個位址時,使用第一個位址連線。以下檢查不會修改網路介面位址、路由或防火牆,適合先建立完整的證據鏈。
一、固定查詢目標,記錄原始錯誤
先保存應用程式錯誤訊息、查詢名稱、記錄類型與發生時間。同時釐清是所有網域名稱都解析失敗,還是只有某個名稱失敗;異常發生在主機上的程序,還是容器中的程序。短名稱會受到搜尋網域影響,排查時應優先使用結尾帶點的完整網域名稱。
以下以 amdssh.com. 示範查詢格式,不預設它一定要回傳某個位址。實際驗收時,應替換成業務所需、且已確認存在對應記錄的名稱。先檢查工具是否可用,再保存基礎環境資訊:
command -v getent resolvectl dig
date -Is
readlink -f /etc/resolv.conf
cat /etc/resolv.conf
grep '^hosts:' /etc/nsswitch.conf
systemctl is-active systemd-resolved
resolvectl status
dig 由 dnsutils 套件提供;若尚未安裝,應透過已設定的套件來源準備工具。名稱解析已經故障時,安裝失敗不能當作新的根本原因證據。
位址能連通,不代表 DNS 查詢路徑正常。DNS 收到回應,也不代表應用程式取得了所需記錄;必須一併檢查回應狀態、記錄類型與實際回傳內容。
二、比對 NSS 與系統解析服務
三種查詢並不等價
getent 透過 NSS 查詢,較接近常見的系統位址解析呼叫;resolvectl 查詢 systemd-resolved;dig 則執行 DNS 查詢,無法驗證完整的 NSS 路徑。
getent ahostsv4 amdssh.com.
resolvectl query --type=A amdssh.com.
dig amdssh.com. A +time=2 +tries=1
應綜合比對這三項結果。若 getent 回傳舊位址,而 DNS 查詢回傳新位址,先檢查 /etc/hosts 與 hosts: 行中的模組順序。若 resolvectl 成功但 getent 失敗,應檢查 NSS 模組是否存在、順序是否合理,以及服務是否在不同的檔案系統環境中執行。
/etc/resolv.conf 可能指向本機解析入口,而不是直接列出最終上游伺服器。它也可能由網路管理工具產生。不要因為看到本機位址就認定設定有誤,也不要先覆寫符號連結,再判斷故障是否消失。
有些應用程式使用自己的 DNS 函式庫,不經過 NSS。因此,getent 成功只能證明系統解析路徑正常,不能證明所有應用程式都已恢復。
三、指定上游,區分回應與傳輸故障
從 resolvectl status 記錄故障查詢所對應網路介面的 DNS 伺服器、路由網域與目前使用的伺服器。具有多個網路介面的主機可能依網域名稱選擇不同上游,不能只取輸出中的第一項。以下以互動方式輸入實際使用的上游位址,不引入未經確認的公共解析器。
read -r -p 'DNS server address: ' DNS_SERVER
dig @"$DNS_SERVER" amdssh.com. A +time=2 +tries=1
dig @"$DNS_SERVER" amdssh.com. A +tcp +time=2 +tries=1
dig @"$DNS_SERVER" amdssh.com. AAAA +time=2 +tries=1
這裡的兩秒逾時與一次嘗試是排查參數,不是業務逾時設定的建議。請保留完整輸出,重點查看 status、答案區、查詢耗時與實際使用的伺服器,不要只憑指令的結束狀態碼判斷業務記錄是否有效。
依回應狀態處理
NXDOMAIN 表示名稱不存在;應先核對拼字、搜尋網域與權威記錄。NOERROR 但答案區為空,可能只是沒有該類型的記錄,不應視為網路故障。SERVFAIL 表示解析過程失敗,需要配合上游日誌或請管理方協助檢查;REFUSED 則應核對查詢權限。
UDP 查詢逾時而 TCP 查詢成功,表示兩種傳輸路徑的表現不同,可進一步檢查相關網路政策。若兩者都逾時,應檢查通往該上游的路由與存取政策,但不能僅憑逾時就判定伺服器停機。若上游有回應,但系統解析路徑失敗,則應回到本機設定與快取繼續定位問題。
四、依據證據修復,避免覆寫設定管理者的輸出
先查明 DNS 設定由哪一層管理。Ubuntu Server 可能透過 Netplan 將設定交給特定網路後端,也可能採用其他管理方式。要讓設定持續生效,應修改實際管理者的設定檔,不能只修改產生出來的 /etc/resolv.conf。
若已確認權威記錄修正完成,但 systemd-resolved 仍保留舊結果,可以在保存故障現場資訊後清除其快取:
resolvectl statistics
sudo resolvectl flush-caches
resolvectl query --type=A amdssh.com.
getent ahostsv4 amdssh.com.
清除快取不會更改上游,也不會清除應用程式自己的快取。若名稱先前曾回傳不存在,也可能受到負向快取影響,應搭配回應中的 SOA 資訊判斷,不能把反覆重新啟動服務當作修復方式。
修改 NSS 順序前,應保存原始檔案,並釐清哪些模組負責本機檔案、DNS 或其他名稱來源。帶有條件動作的模組可能提前結束查詢,不能只看有沒有 dns 字樣。
若確實需要修改持久性 DNS 設定,應先備份設定、檢查語法,並準備還原原始檔案的步驟。遠端套用網路變更前,應保持既有 SSH 連線,優先使用設定管理工具提供的可回復套用方式;不要同時更改 DNS、路由與網路介面名稱。
五、在業務程序的環境中完成驗收
主機恢復後,還要檢查容器或隔離服務所看到的解析設定檔。容器可能有獨立的 /etc/resolv.conf,程序也可能快取了舊位址。應進入實際執行環境重複查詢,而不是只在主機終端機執行同一個指令。
最終驗收包括以下檢查項目:
- 針對業務使用的完整網域名稱,分別查詢所需的記錄類型,核對位址與預期用途。
- 同時確認 NSS、系統解析服務與實際使用的上游結果。
- 執行一次真實業務請求,區分名稱解析失敗與後續連線失敗。
- 檢查應用程式是否固定使用舊位址,以及是否需要透過其管理介面更新快取。
- 確認設定由正確的管理者持久保存;在受控重新啟動後,檢查設定是否遭到覆寫。
- 保留修改前後的輸出、設定差異與業務請求結果,避免只記錄「已經恢復」。
若問題只發生在某個程序,應繼續檢查它的解析器、執行環境與連線池,而不是擴大為整台主機的網路調整。完整的排查應能解釋原始錯誤、指出故障層,並證明修復後的業務請求走的是預期解析路徑。
常見問題
dig 查得到記錄,為何應用程式仍無法解析?
dig 直接執行 DNS 查詢,通常不走完整的 NSS 路徑。hosts 設定、容器內的解析檔案及應用程式快取都可能不同,應對照 getent 結果,並在出錯程序的實際環境中重做檢查。
清除系統 DNS 快取就能排除所有解析問題嗎?
不能。resolvectl flush-caches 只清除 systemd-resolved 的快取,不會修正上游錯誤或清除應用程式自己的快取。應先記錄回應狀態與使用中的上游,再處理對應層級。