WireGuard DNS 失效的 3 種原因與修正方法
WireGuard 通道已啟用卻無法解析名稱,或 DNS 查詢外洩至本機路由器?本文釐清 3 種失敗模式,逐一修正解析器、路由與設定覆寫問題。
WireGuard 通道一啟用,DNS 為何立即失效
WireGuard 的 DNS 會以 3 種方式失效,每種都有對應的修正方法。可能是完全無法解析,也可能是名稱可以解析,但查詢未經通道而離開電腦;或者用戶端自身的解析器管理程式會在介面啟動幾秒後覆寫設定。問題幾乎從來不在通道本身,而在於哪一行告訴用戶端要查詢哪個解析器,以及決定封包如何前往該解析器的路由。
WireGuard 傳輸 IP 封包,並不了解 DNS(domain name system,將 example.com 等名稱轉換為 IP 位址的服務)。用戶端 [Interface] 區塊中的 DNS = 行不是 WireGuard 設定。它會由 wg-quick 讀取;wg-quick 是負責啟動介面的 shell wrapper,而 wg-quick 會在通道運作期間修改用戶端的解析器設定,並在通道於 wg-quick down 上停用時還原。因此,以下每個問題都是路由問題或 wg-quick 問題,絕不是密碼編譯問題。如果尚未建立通道,請先參閱在自己的 VPS 上自架 WireGuard VPN,然後再返回本頁。
在處理 DNS 前,先確認通道運作正常。
sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1wg show 應列出具有最新 latest handshake 的對等端,且 2 個 ping 都應收到回應。如果 ping 1.1.1.1 逾時,這是轉送或 NAT(network address translation)問題,而不是 DNS 問題;調整多少解析器設定都無法解決。本文所有範例都使用 10.8.0.0/24 作為通道子網路,並使用 10.8.0.1 作為伺服器的通道位址。請替換為您自己的設定。
失敗一:解析器沒有回應,因此任何名稱都無法解析
症狀很明確。ping 1.1.1.1 可以運作,而 curl https://example.com 回傳以下內容:
curl: (6) Could not resolve host: example.com直接從用戶端向通道解析器發出查詢。dig 來自 Ubuntu 和 Debian 的 dnsutils 套件。
dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.com第一個命令會回傳位址,表示封包可以透過通道抵達網際網路。第二個命令沒有回傳任何內容,並顯示 ;; communication timed out; no servers could be reached。診斷結果就是這樣:您的用戶端指向 10.8.0.1,而 10.8.0.1 沒有在 UDP port 53 上回應。
原因有兩個。伺服器上可能沒有執行解析器,或伺服器防火牆在查詢抵達前將其丟棄。請在伺服器上檢查這兩項。
sudo ss -ulnp | grep ':53'
sudo nft list ruleset正常執行且繫結正確的解析器會顯示包含 10.8.0.1:53 或 0.0.0.0:53 的行。在 Ubuntu 上,通常令人困惑的是 127.0.0.53:53:這是 systemd-resolved 的 stub listener。它會繫結至 loopback 位址,並刻意不允許其他機器存取。若 VPN 用戶端指向一部唯一解析器是該 stub 的伺服器,就會產生完全相同的逾時。
修正方式是讓解析器監聽通道位址,並加入一條允許對等端存取的防火牆規則。
sudo apt update && sudo apt install -y unbound
printf 'server:\n interface: 10.8.0.1\n access-control: 10.8.0.0/24 allow\n' \
| sudo tee /etc/unbound/unbound.conf.d/wireguard.conf
sudo systemctl restart unbound
sudo ss -ulnp | grep '10.8.0.1:53'接著只允許通道流量使用該 port。使用 nftables 時,將以下兩行加入 /etc/nftables.conf 中的 input chain,然後使用 sudo systemctl reload nftables 重新載入。
udp dport 53 iifname "wg0" accept
tcp dport 53 iifname "wg0" accept使用 ufw 時,sudo ufw allow in on wg0 to any port 53 會執行相同工作。絕對不要將 port 53 開放給公用網際網路。掃描器會在數天內找到開放的遞迴解析器,並利用它放大阻斷服務攻擊;您的供應商可能會在您發現前注意到這些流量。
從用戶端重新執行 dig +short @10.8.0.1 example.com。輸出中出現位址表示解析器路徑正常,因此用戶端現在只需使用該解析器。將該行加入用戶端的 [Interface] 區塊,然後使用 sudo wg-quick down wg0 && sudo wg-quick up wg0 重新啟動介面。
[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1失敗 2:DNS 洩漏,因為分割通道不會路由解析器
這個問題更嚴重,因為表面上一切都正常。名稱可以解析,網頁可以載入,但查詢會以明文通過你原本不想信任的本機網路。
有兩種設定會造成這個問題。第一種是用戶端設定了 AllowedIPs = 0.0.0.0/0, ::/0,但沒有 DNS = 行。wg-quick 會在自己的路由表中安裝預設路由,並使用 suppress_prefixlength 0 新增規則。這會刻意保留更具體的本機路由,讓電腦仍可連線到印表機。用戶端透過 DHCP 取得的解析器通常是 192.168.1.1 的路由器,且會符合其中一條本機路由。你的流量會通過通道,但本機網路仍會收到你查詢的完整名稱清單。
第二種是分割通道:設定 AllowedIPs = 10.8.0.0/24 和 DNS = 9.9.9.9。因為 9.9.9.9 不在 AllowedIPs 內,用戶端沒有可經由通道連線到它的路由,因此查詢會像第一種情況一樣,經由本機連線送出。
確認實際回應的解析器。whoami.akamai.net 是一個公開測試名稱,會以發出查詢的遞迴解析器 IP 位址回應,因此你可以將該回應與伺服器的公開位址比較。
resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53resolvectl status 會為每個連線列印一個區塊。如果乙太網路或無線連線的區塊仍顯示 Current DNS Server: 192.168.1.1,而 wg0 區塊沒有顯示任何內容,這就是洩漏。dig +short whoami.akamai.net 回傳你的家用寬頻位址,而不是伺服器位址,便可從遠端確認這一點。tcpdump 行是判定結果的依據:正常輸出會將所有連接埠 53 封包放在 wg0 上;發生洩漏時,封包則會出現在 wlan0 或 enp3s0 上。
修正方式分為兩部分,且兩者都必須完成。將 DNS 設定為通道內的位址,並確認該位址位於 AllowedIPs 內。
[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/1610.8.0.1 位於 10.8.0.0/24 內,因此查詢會加密後傳送至伺服器。如果你堅持在分割通道中使用公開解析器,請將它新增為主機路由:AllowedIPs = 10.8.0.0/24, 9.9.9.9/32。封包接著會經由通道傳送,但本機網路仍可從先前的工作階段看出你選用了哪個供應商。自行執行解析器即可避免這個問題。
解析器指派是手動建置 WireGuard 與協調式網狀網路之間的明顯差異之一,也是 WireGuard 與 Tailscale 的比較 中的取捨。執行 自行託管的 Headscale 控制伺服器,即可取得這項協調功能,而不必將金鑰資料交給第三方。
Linux 用戶端的故障三:resolvconf 與 systemd-resolved 發生衝突
macOS、Windows、iOS 和 Android 用戶端會透過官方應用程式套用 DNS =,通常不會造成太多問題。Linux 的設定則由 shell script 套用,而該 script 必須判斷系統使用多種 resolver manager 中的哪一種。
第一種故障會直接顯示錯誤。sudo wg-quick up wg0 會停止並顯示:
resolvconf: command not foundwg-quick 會呼叫 resolvconf,但系統未安裝該執行檔。請安裝可與 systemd-resolved 通訊的實作,然後重新啟用介面。
sudo apt install -y openresolv
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0第二種故障不會顯示錯誤,也是最耗費排查時間的一種。介面已啟用,resolvectl status wg0 也正確顯示 DNS Servers: 10.8.0.1,但名稱解析仍使用舊的 resolver。systemd-resolved 會為每個 link 維護獨立的 resolver 清單,並為每個查詢選擇一個 link。除非將某個 link 標記為名稱解析的預設路由,否則它會繼續使用無線 link 的 resolver,因為該 link 具有 search domain,而目前的 link 沒有。
請在同一個步驟中設定 resolver,並指定預設路由。%i 會展開為介面名稱,因此此區塊可在任何介面上直接使用。
[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %i使用此方式設定 PostUp 時,請刪除 DNS = 行。否則會有兩種機制寫入 resolver 狀態,之後只有其中一種會進行清理。~. 引數是關鍵部分:它會將 wg0 標記為所有名稱的 routing domain,因此 systemd-resolved 會將所有查詢傳送到該 link,而不是逐一查詢選擇 link。請進行驗證。
resolvectl status wg0正常輸出會包含 DNS Servers: 10.8.0.1 和 Default Route: yes。如果 Default Route 讀取為 no,表示 resolvectl domain 部分未執行,系統又回到 link selection。
還有一種情況值得特別指出。如果 /etc/resolv.conf 是實體檔案,而不是指向 /run/systemd/resolve/stub-resolv.conf 的 symbolic link,表示該檔案由其他元件管理,通常是 NetworkManager 或 container runtime。請先執行 ls -l /etc/resolv.conf,再進行其他排查,因為某個工具可能會在每次網路變更時重寫該檔案,並在最不適當的時機撤銷你的設定。
升級:透過通道使用自有的過濾解析器
查詢能穩定通過通道傳送後,遠端的解析器就會成為控制點。在該處執行 AdGuard Home,即可讓所有連線裝置使用封鎖清單過濾和查詢記錄,無需安裝用戶端軟體,也不必逐台設定。官方安裝指令碼截至 July 2026 已確認,只有一行。
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v首次執行時,設定精靈會監聽 port 3000。請透過通道存取 http://10.8.0.1:3000,不要將該 port 公開;並在精靈中將 DNS 監聽位址和管理介面監聽位址都設定為 10.8.0.1。如果失敗一中的 unbound 仍使用相同位址,請先以 sudo systemctl disable --now unbound 停止它,因為同一個位址上的 UDP port 53 無法由兩個程序繫結,後啟動的程序會以 listen udp 10.8.0.1:53: bind: address already in use 結束。
如果用戶端設定已指定 DNS = 10.8.0.1,就不需要變更。現在,查詢記錄會顯示每個對等端的所有查詢。這是實際的隱私決策,不是無條件的好處:你會把信任對象從網際網路服務供應商轉為自己,也必須負責讓該主機保持修補更新。暴露於網際網路的伺服器必須先完成基本防護,而新 VPS 的前十分鐘涵蓋了這些事項。
FAQ
為什麼我的 WireGuard 通道已連線,但名稱無法解析?
通道只傳送封包,完全不處理名稱。因此,通道正常但查詢失敗,表示您指定的 resolver 沒有回應。請在用戶端使用 dig +short @10.8.0.1 example.com 進行測試。收到 communication timed out 回應,表示該通道位址上沒有 resolver 監聽,通常是因為 systemd-resolved stub 只繫結至 127.0.0.53,或伺服器防火牆丟棄了從 wg0 進入的 UDP port 53 流量。請先修正監聽端,再僅為 wg0 開放該 port。
如何確認 DNS 是否透過 WireGuard 洩漏?
請在用戶端執行 sudo tcpdump -ni any -c 10 port 53,並在瀏覽時監看介面欄位。所有封包都應該使用 wg0。如果封包出現在無線或 ethernet 介面上,表示查詢正以明文傳送。dig +short whoami.akamai.net 可提供第二個檢查結果,因為它會回覆發出查詢之 recursive resolver 的公用位址。因此,如果回應不是您伺服器的位址,即可確認發生洩漏。
使用 split tunnel 時,是否仍需要 DNS = 行?
需要,而且 resolver 位址也必須位於 AllowedIPs 內,否則用戶端沒有通往該位址的路由。使用 AllowedIPs = 10.8.0.0/24 時,位於 10.8.0.1 的 resolver 會受到涵蓋,查詢也會加密。9.9.9.9 等公用 resolver 不在涵蓋範圍內,因此即使 DNS 行看似正確,查詢仍會透過本機連結送出。
為什麼 resolvectl 顯示正確的伺服器,但查詢仍會送往其他位置?
systemd-resolved 會為每個連結維護一份 resolver 清單,並為每個查詢選擇一個連結。因此,當其他連結持有名稱解析的預設路由時,wg0 上的正確項目會被忽略。請將 PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. 加入用戶端的 [Interface] 區塊,並移除 DNS = 行。之後,resolvectl status wg0 應會回報 Default Route: yes。
多個用戶端發生問題時,應先修正哪一個?
請先修正一個 Linux 用戶端,因為只有它能顯示運作機制。resolvectl status 和 tcpdump 會告訴您哪個 resolver 回應,以及封包經由哪個介面傳送。手機與桌面應用程式會套用相同的 DNS 和 AllowedIPs 值,但不會顯示底層配置。因此,Linux 用戶端正確後,您即可複製一份已驗證的配置。