很多朋友裝好我之後網頁照樣打不開,最後發現問題不在節點,而是出在 DNS——網域一開始就被解析到了錯誤的 IP,代理做得再好也是白費工夫。這篇文章講清楚我的 DNS 模組該怎麼設定,把汙染和洩露這兩個坑一次填平。

為什麼 DNS 需要特別處理

正常上網時,瀏覽器會先問 DNS 伺服器「這個網域的 IP 是多少」,再向那個 IP 發起連線。問題就出在兩個環節:

  • DNS 汙染:使用 ISP(網路服務商)DNS 查詢某些網域時,回傳的是偽造的 IP,連線自然會失敗或逾時。
  • DNS 洩露:流量走了代理,但 DNS 查詢卻還在本地以明文發出,等於把你造訪了哪些網站原樣廣播出去。

所以我內建了一個 DNS 模組:開啟後,裝置上所有 DNS 查詢都會先經過我,由我決定用哪台伺服器解析、要不要透過代理去解析。

fake-ip 與 redir-host 的差異

enhanced-mode 有兩個可選值,決定了我怎麼回應系統的 DNS 查詢:

模式運作方式優缺點
fake-ip 立刻回傳一個保留段的假 IP(198.18.x.x),真正的解析延後到建立連線時才進行 回應快、無洩露;少數會檢測真實 IP 的程式(例如某些遊戲、網路銀行 App)可能不相容
redir-host 老老實實查出真實 IP 再回傳 相容性最好;但解析結果可能被汙染,且規則比對的時機更晚

結論:日常首選 fake-ip。遇到不相容的應用程式,用 fake-ip-filter 把它排除掉即可,不必整體退回 redir-host:

fake-ip-filter 範例
dns:
  enhanced-mode: fake-ip
  fake-ip-filter:
    - "*.lan"
    - "+.stun.*.*"
    - "+.battle.net"       # game launchers often need real IP
    - "time.windows.com"

nameserver 與 fallback 的分工

這是整個 DNS 設定裡最容易配錯的部分。正確的心智模型是:

  • nameserver:主力解析組,放你的 ISP(網路服務商)DNS 或當地慣用的 DNS,解析本地網域又快又準。
  • fallback:備用解析組,放全球通用的加密 DNS(DoH/DoT,例如 Cloudflare、Google),專門處理可能被汙染或劫持的網域。

兩組會同時併發查詢。當查詢結果命中 fallback-filter 的條件(例如解析出的 IP 落在可疑範圍),我就採用 fallback 的結果,藉此避開汙染:

建議的完整 DNS 設定
dns:
  enable: true
  listen: 0.0.0.0:53
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 1.1.1.1                         # Cloudflare
    - 8.8.8.8                         # Google
  fallback:
    - https://1.1.1.1/dns-query       # Cloudflare DoH
    - https://dns.google/dns-query    # Google DoH
  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4                   # bogus IPs returned by poisoning

這份設定的效果:日常網域走 Cloudflare/Google 這類公共 DNS 就能快速解析;一旦解析結果可疑,就自動改用加密 DNS 的結果,汙染防住了,查詢也不會以明文外洩。你也可以把 nameserver 換成自家 ISP 提供的 DNS,通常對本地網站的解析速度會更快。

如何驗證設定生效

  1. 打開控制面板的「日誌」頁,把等級調到 debug,就能看到每一條 DNS 查詢用了哪個伺服器。
  2. 造訪 dnsleaktest.com 做洩露測試:顯示出來的 DNS 伺服器應該是你在 fallback 裡設定的(或節點端的),而不是本地 ISP 的。
  3. nslookup 查一個已知會被汙染的網域,若回傳 198.18 開頭的假 IP,就代表 fake-ip 正常運作。
常見雷區 改完 DNS 設定後記得重新載入設定檔,並清空瀏覽器的 DNS 快取(在 Chrome 網址列輸入 chrome://net-internals/#dns);Android 端還要重新啟動一次連線才會全部生效。

路由器全域代理下要多留意什麼

如果我跑在路由器或 NAS 上,替全家裝置做透明代理,DNS 設定的重要性會再提高一個層級——因為這時已經沒有「裝置自己解析」這條退路,所有裝置的網域解析都要經過我這一關。這種情境下有兩點建議:

  • listen 綁定到區域網路網卡:預設只監聽 127.0.0.1 的話,其他裝置的 DNS 請求根本進不來,記得改成 0.0.0.0:53,並在路由器的 DHCP 選項裡把閘道同時設為 DNS 伺服器。
  • 替智慧電視、遊戲主機另外開白名單:這類裝置的連網驗證邏輯往往比較僵化,一旦 DNS 結果和它預期的地理位置不符就直接罷工,遇到這種情況優先加進 fake-ip-filter,而不是整個關掉 fake-ip。

另外提一句,很多人喜歡直接填 8.8.8.8 當主要 DNS,圖個簡單省事。但在某些網路環境下存取 Google DNS 本身就可能繞路或逾時,拿它當主力解析反而更慢——記住前面那條分工原則:nameserver 交給距離近、速度快的 DNS,fallback 才輪到加密 DNS 出場。

兩個常見誤解

最後澄清兩個新手常有的誤會,省得走彎路:

  1. 「開了 fake-ip 我就再也看不到真實 IP 了」——不是的,fake-ip 只是把系統層面看到的 IP 換成了假位址,我內部依然會在建立連線時完成真實解析,日誌和連線頁面照樣能看到目標的真實 IP,不影響你排查問題。
  2. 「DNS 設定越複雜越安全」——恰恰相反,nameserver 和 fallback 各放兩三個就夠用,塞太多伺服器只會拖慢第一次查詢的耗時(因為要等併發結果都回來),簡潔清楚遠比「大而全」更實用。

把這份 DNS 設定抄進你的 config.yaml,重新載入一次,基本上就能和汙染、洩露這兩個老大難問題說再見了。

和規則分流的連動:DNS 也能參與決策

如果你的規則集裡用了 GEOIP 判斷,DNS 解析結果會直接影響分流是否準確——解析錯了 IP,GEOIP 自然也判斷錯地區,最終可能把本地網站送去了代理、或是把該走代理的網站直接放行。這也是為什麼要強調「先把 DNS 配對好,再談規則調校」的順序:地基沒打好,上層規則寫得再精細也只是空中樓閣。遇到「某個網站分流結果不符合預期」,不妨先懷疑一下是不是 DNS 解析本身就出了偏差,而不是急著去改規則。

小結

這篇文章其實只講了一件事:讓該走的網域走該走的路,別讓 DNS 拖了後腿。回顧一下核心結論——首選 fake-ip,遇到不相容的應用程式用篩選清單排除而不是整體退回;nameserver 負責本地網域,fallback 負責可能被汙染的境外網域,兩者分工明確、互不越界;設定改完記得清快取、重新載入、再驗證,三步走完才算真正生效。把這些原則記牢,日後無論換裝置、換客戶端,都能很快配出一份穩妥的 DNS 設定,不用每次都從頭摸索。

如果你是剛接觸我的新手,建議先照抄本文給出的完整設定範例跑起來,觀察一段時間沒問題之後,再依照自己的網路環境微調 nameserver 和 fallback 裡的具體伺服器位址——先跑通,再最佳化,比一開始就追求完美更省心。