Mihomo DNS 設定教學:nameserver、fallback 與 DNS 劫持
說明 nameserver、fallback、fallback-filter 與 dns-hijack 的設定方式,解析 fake-ip 和 redir-host 的差異,並提供可直接套用的 YAML 範例。
DNS 設定的三個環節:入口、解析與連線
排查 Clash Meta(mihomo)的 DNS 問題時,請先釐清三個環節:應用程式將查詢送給誰、核心向哪個上游查詢,以及取得結果後連線會套用哪條規則。網頁無法開啟,問題可能出在其中任何一個環節。只更換 nameserver,無法解決系統未將 DNS 請求送進核心的問題。
- 入口:
dns.listen開啟核心的 DNS 監聽連接埠;使用 TUN 時,dns-hijack會接管符合條件的 DNS 流量。 - 解析:
nameserver、fallback和nameserver-policy決定查詢哪些上游,以及如何選擇結果。 - 連線:應用程式取得 IP 位址後發起連線,核心再依代理模式、規則與策略群組處理流量。
系統 HTTP 代理通常不會自動接管所有應用程式的 DNS。瀏覽器的安全 DNS、Android 私人 DNS,以及應用程式內建的 DoH,也可能使用獨立通道。因此,「已啟用系統代理」不代表「所有 DNS 查詢都經過 Mihomo」。
nameserver 與 default-nameserver:上游與引導解析
nameserver 是一般網域查詢使用的上游伺服器清單。直接填入 IP 位址通常代表一般 DNS;https:// 表示 DoH,tls:// 表示 DoT。一般 DNS 常用連接埠為 53,DoT 預設使用 853,DoH 通常使用 HTTPS 的 443 連接埠。
上游若設定為 https://dns.alidns.com/dns-query,核心必須先取得 dns.alidns.com 的 IP 位址。default-nameserver 用來解析 DNS 伺服器本身的網域,屬於引導解析,不是「所有查詢優先使用的預設伺服器」。此欄位填入 IP 位址,可避免一開始就依賴尚未解析的網域名稱。
| 欄位 | 用途 | 常見誤解 |
|---|---|---|
listen | 設定本機 DNS 監聽位址與連接埠 | 設定後系統就會自動使用 |
default-nameserver | 解析 DNS 上游伺服器的網域名稱 | 它是所有網域的優先解析伺服器 |
nameserver | 處理一般 DNS 查詢 | 多個位址一定會依清單順序逐一嘗試 |
proxy-server-nameserver | 專門解析代理節點的網域名稱 | 它負責所有透過代理造訪的網站 |
nameserver-policy | 為符合條件的網域指定解析上游 | 它會直接決定網站連線使用哪個節點 |
代理節點本身若使用網域名稱,也需要 DNS 解析。可以透過 proxy-server-nameserver 指定可連線的上游,避免陷入「必須先連上代理,才能解析代理位址」的循環。這和網站連線的規則分流是兩回事,不能互相取代。
fallback 與 fallback-filter:並行查詢後如何選擇結果
不要把 fallback 簡單理解為傳統的「主要 DNS 逾時後才啟用的備用伺服器」。在需要搭配 fallback 選擇結果的一般解析流程中,核心會同時向相關上游發出查詢,再依篩選條件判斷是否採用 fallback 的結果。因此,加入 fallback 可能會讓同一次網域查詢送到兩組解析服務。
三種常用篩選條件
geoip:啟用依 IP 位址所屬地區進行判斷的功能;搭配geoip-code指定地區代碼。例如設為CN時,一般解析結果不符合該地區條件,就會改採 fallback 結果。此判斷仰賴 GeoIP 資料。ipcidr:一般解析結果落在指定的 IP 網段時,改採 fallback。此條件比對的是 IP 位址範圍,不是網域名稱。domain:符合條件的網域直接採用 fallback 結果。範例中的+.github.com表示根網域及其子網域。
以下完整 DNS 片段明確設定 geoip: false,僅示範網段與網域條件,避免初次設定時混入 GeoIP 資料更新問題。0.0.0.0/8 與 240.0.0.0/4 僅作為異常結果篩選範例,並非完整的污染位址清單,也無法辨識所有錯誤解析。
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter-mode: blacklist
fake-ip-filter:
- localhost
- "+.lan"
- "+.local"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
proxy-server-nameserver:
- https://dns.alidns.com/dns-query
nameserver:
- https://dns.alidns.com/dns-query
fallback:
- https://cloudflare-dns.com/dns-query
fallback-filter:
geoip: false
ipcidr:
- 0.0.0.0/8
- 240.0.0.0/4
domain:
- "+.github.com"
此範例要求列出的上游伺服器在目前網路與路由條件下都能連線。DoH 使用加密傳輸,但加密不代表流量會自動經過代理;上游連線的實際路徑仍由相關設定決定。如果網路無法連上某個上游,請先改用已確認可連線的服務,不要一次加入多組未知位址。
fake-ip 與 redir-host:回傳給應用程式的位址不同
enhanced-mode: fake-ip 會針對適用的 DNS 查詢回傳映射位址。應用程式連線至該位址時,核心會透過映射找回網域名稱,再套用規則處理。範例中的 198.18.0.1/16 屬於基準測試專用位址範圍;看到此範圍的回應時,不應立刻判定 DNS 遭到污染。
redir-host 則會將實際解析到的位址回傳給應用程式,再透過網域名稱與 IP 位址的關聯協助處理連線。這種方式較接近傳統 DNS 行為,但遇到共用 IP、多個網域指向同一位址,或應用程式使用快取時,網域關聯可能不如 fake-ip 直接。
| 項目 | fake-ip | redir-host |
|---|---|---|
| 應用程式取得的位址 | 通常是映射位址,排除篩選項目 | 上游回傳的實際位址 |
| 適合優先測試的情境 | TUN 接管與依網域進行規則分流 | 應用程式必須取得實際位址的相容性情境 |
| 檢查重點 | 連線是否也回到持有映射資料的核心 | DNS 解析結果與連線是否仍能互相關聯 |
篩選清單只會改變回傳位址的方式
範例中的 fake-ip-filter-mode: blacklist 表示清單中的比對項目不會回傳 fake-ip。為區域網路後綴加入篩選,可避免向這些名稱回傳映射位址,但不保證名稱一定能解析。.local 通常與 mDNS 有關;區域網路裝置也可能只登記在路由器 DNS 中,公用 DNS 並不知道這些名稱。
因此,NAS 名稱仍無法解析時,應先確認它仰賴 mDNS 還是路由器 DNS,再決定是否加入區域網路解析策略。不要為了迴避問題而將所有網域都加入篩選。切換兩種模式後,也應清除舊 DNS 快取並重新建立連線,避免應用程式繼續使用先前取得的位址。
TUN 的 dns-hijack:接管連接埠 53 的查詢
dns-hijack 位於頂層的 tun 區段,不在 dns 區段內。以下片段適用於支援相應 TUN 設定的桌面用戶端。此設定需要建立 TUN 的權限;用戶端也可能透過服務模式或權限輔助程式管理相關設定。
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53會接管進入 TUN 且符合條件的 UDP 53 連接埠 DNS 查詢。tcp://any:53會一併接管 TCP 53 連接埠,涵蓋使用 TCP 的一般 DNS 查詢。auto-route用於自動設定相關路由,但能否涵蓋特定應用程式,仍取決於系統路由與用戶端實作。auto-detect-interface用於自動偵測出口網路介面;使用多張網卡或特殊路由時,仍須確認實際出口。
此處的「any」不代表能攔截網路上的所有 DNS。只有進入接管路徑的流量才有機會被處理;瀏覽器透過 HTTPS 443 連接埠傳送的 DoH,也不會因此自動轉成一般 DNS。DoT 的 853 連接埠同樣不在上述兩個比對項目內。
範例中的 DNS 監聽位址為 127.0.0.1:1053,適合在本機測試。一般系統 DNS 設定介面通常只接受位址,不接受自訂連接埠;直接填入 127.0.0.1 會查詢連接埠 53,而不是 1053。TUN 內部的 DNS 劫持與手動設定系統 DNS 是兩種不同的入口,請勿混為一談。
依序驗證:監聽、上游、接管與規則
第一步:確認最終設定與監聽連接埠
重新載入設定後,先查看用戶端記錄,確認是否有 YAML 解析失敗、不支援欄位或連接埠綁定失敗等訊息。重點檢查最終設定中的 dns.enable、listen 與 enhanced-mode。各用戶端的選單名稱不盡相同,請找出實際執行設定或設定預覽,不要只查看訂閱原始內容。
在 macOS、Linux 或已安裝 dig 的環境中,可直接向連接埠 1053 發出查詢。第一個測試使用 UDP,第二個使用 TCP;這些是驗證指令,不代表已預先測得特定結果。
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
在 fake-ip 模式下,未被篩選的 A 記錄查詢通常會回傳映射範圍內的位址。這只能確認目前的 DNS 入口有回應,無法單獨證明遠端網頁可正常存取。還須確認連線是否進入同一個核心,以及節點是否能建立連線。
第二步:判斷是上游無法連線,還是入口未被接管
- 指定連接埠 1053 查詢也逾時:先確認監聽是否成功,再檢查上游連線錯誤。必要時暫時只保留一個已確認可連線的 nameserver,縮小排查範圍。
- 指定連接埠 1053 有回應,但應用程式仍使用其他 DNS:檢查 TUN 是否啟用、路由是否生效,以及瀏覽器的安全 DNS 是否使用其他通道。
- 網域可以解析,但網頁仍無法開啟:檢查連線記錄中的規則命中結果、策略群組選擇與節點錯誤,不要再盲目更換 DNS。
- 只有區域網路名稱無法解析:確認路由器 DNS 或 mDNS 的解析路徑,並檢查是否需要專用的區域網路策略。
第三步:清除快取後重新測試
Windows 可在終端機執行 ipconfig /flushdns。macOS 可依序執行以下兩個指令,第二個指令需要管理員授權。瀏覽器與應用程式可能也有自己的快取;清除系統快取後,請關閉舊連線,再重新嘗試連線。
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
要確認 DNS 查詢是否仍送往非預期的伺服器,應同時觀察系統、瀏覽器與核心的實際行為。只看到 DoH 位址,或只造訪一次 DNS 檢測網站,都不足以說明所有程序的解析路徑。fallback 的並行查詢、瀏覽器獨立使用的 DoH,以及系統背景請求,都需要分開判斷。
合併設定與後續調整
同一個 YAML 檔案不要重複加入兩個頂層 dns: 或兩個 tun:。重複的鍵值可能會遭解析器拒絕,也可能讓其中一段覆蓋另一段。請將範例欄位合併到現有區段,並確認用戶端套用覆寫的順序;訂閱更新後,再檢查執行中的設定是否保留。
- 先建立可用的基準設定:確認單一上游可以連線,且本機 1053 查詢正常,再加入 fallback 與 TUN 接管。
- 再處理特定網域:需要依網域指定解析上游時,使用 nameserver-policy;需要設定連線分流時,修改 rules,並分別驗證兩者。
- 最後處理 IPv6:範例中的
dns.ipv6: false用於停用 DNS 的 AAAA 回應,不代表停用作業系統的所有 IPv6 功能,也不會阻止應用程式使用已取得的 IPv6 位址。 - 保留復原步驟:若發生整體斷網,先停用 TUN、還原原本的系統 DNS 與代理設定,再載入備份;不要繼續疊加未知設定。
若要進一步確認規則與 TUN 設定之間的關係,請參閱DNS 設定手冊與TUN 設定說明。排除問題的關鍵是每次只調整一個環節:先確認請求進入核心,再確認上游有回應,最後檢查連線規則。如此才能判斷是哪項修改解決了問題。