SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-28

WireGuardのDNSが使えない3つの原因と対処法

WireGuardは接続済みなのに名前解決できない、またはDNSクエリがローカルルーターへ漏れる問題を、3つの失敗パターン別に確認して直します。

WireGuard トンネルが起動すると DNS がすぐに機能しなくなる理由

WireGuard 経由の DNS は、3 通りの問題によって失敗します。それぞれに固有の対処方法があります。まったく名前解決できない場合、名前解決はできてもクエリがトンネルの外へ送信される場合、またはインターフェースの起動から数秒後にクライアント自身のリゾルバ管理ツールが設定を上書きする場合です。ほとんどの場合、問題はトンネルではありません。原因は、クライアントが問い合わせるリゾルバを指定する 1 行と、そのリゾルバまでパケットをどの経路で送るかを決めるルーティングにあります。

WireGuard は IP パケットを転送するだけで、DNS(example.com のような名前を IP アドレスに変換するドメインネームシステム)については認識しません。クライアントの [Interface] ブロックにある DNS = 行は、WireGuard の設定ではありません。この行は、インターフェースを起動するシェルラッパーである wg-quick が読み取り、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.1

wg show の出力に最近の latest handshake を持つ peer が表示され、2 つの ping がどちらも応答することを確認します。ping 1.1.1.1 がタイムアウトする場合は、DNS ではなくフォワーディングまたは NAT(ネットワークアドレス変換)の問題です。リゾルバ設定を変更しても解決しません。ping が応答しても、実際のトラフィックを開始するとスループットが急落する場合は、別の問題です。WireGuard の速度低下はほぼ常に MTU に起因する ため、このページの設定が原因ではありません。ここでは、トンネルのサブネットに 10.8.0.0/24、サーバーのトンネルアドレスに 10.8.0.1 を使用します。環境に合わせて置き換えてください。

障害その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

最初のコマンドがアドレスを返すことから、パケットがトンネル経由でインターネットに到達していることを確認できます。2 番目のコマンドは何も返さず、;; communication timed out; no servers could be reached を出力します。診断結果はこれで確定です。クライアントは 10.8.0.1 を参照するよう設定されていますが、10.8.0.1 は UDP port 53 で応答していません。

原因は 2 つあります。サーバーでリゾルバーが動作していないか、サーバーのファイアウォールがクエリを到達前に破棄しています。サーバーで両方を確認します。

sudo ss -ulnp | grep ':53'
sudo nft list ruleset

正常に動作し、正しく bind されたリゾルバーでは、10.8.0.1:53 または 0.0.0.0:53 を含む行が表示されます。Ubuntu でよくある問題は 127.0.0.53:53 です。これは systemd-resolved の stub listener で、loopback address に bind し、他のマシンからは意図的に到達できません。唯一のリゾルバーがこの stub であるサーバーを VPN client の参照先にすると、まったく同じ timeout が発生します。

トンネル address で待ち受けるリゾルバーを用意し、peers から到達できるように firewall rule を 1 つ追加します。

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'

次に、トンネルの traffic に限定して port を開きます。nftables では、/etc/nftables.confinput chain に次の 2 行を追加し、sudo systemctl reload nftables で reload します。

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 を public internet に開放してはいけません。公開された recursive resolver は数日以内に scanner に発見され、denial of service attack の増幅に使われます。その traffic をあなたより先に provider が検知する可能性もあります。

クライアントから dig +short @10.8.0.1 example.com を再実行します。出力に address が表示されれば、resolver path は機能しています。あとは client の [Interface] block にこの行を追加し、sudo wg-quick down wg0 && sudo wg-quick up wg0 で interface を再起動します。

[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1

DNS リーク: split tunnel が resolver を経由させない場合

この問題は、すべてが正常に動作しているように見えるため、より深刻です。名前解決は成功し、ページも読み込まれます。しかし、クエリは信頼したくなかったローカルネットワーク上を平文で通過します。

原因となる構成は2つあります。1つ目は、AllowedIPs = 0.0.0.0/0, ::/0 が設定されていて、DNS = 行がないクライアントです。wg-quick は独自のルーティングテーブルにデフォルトルートを追加し、suppress_prefixlength 0 を使用するルールも追加します。これにより、より具体的なローカルルートを意図的に有効なままにし、マシンがプリンターへ接続できるようにします。クライアントが DHCP で取得した resolver は、通常 192.168.1.1 のルーターであり、これらのローカルルートのいずれかに一致します。ネットワークトラフィックはトンネルを通過しますが、ローカルネットワークには、検索した名前の一覧がそのまま渡ります。

2つ目は、AllowedIPs = 10.8.0.0/24DNS = 9.9.9.9 を使用する split tunnel です。9.9.9.9AllowedIPs の範囲内にないため、クライアントにはそれへトンネル経由で到達するルートがありません。そのため、1つ目の場合と同じように、クエリはローカルリンクから送信されます。

実際に応答している resolver を確認します。whoami.akamai.net は、問い合わせを行った recursive resolver の IP アドレスを返す公開テスト名です。その応答をサーバーの公開アドレスと比較できます。

resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53

resolvectl status はリンクごとに1つのブロックを表示します。ethernet または wireless リンクのブロックに Current DNS Server: 192.168.1.1 が残っていて、wg0 ブロックには何も表示されない場合、それがリークです。dig +short whoami.akamai.net がサーバーのアドレスではなく自宅のブロードバンドアドレスを返せば、外部からも確認できます。tcpdump 行が議論を決着させる証拠です。正常な出力では、すべてのポート 53 パケットが wg0 を通過します。リークがある場合は、wlan0 または enp3s0 を通過します。

修正には2つの手順があり、両方が必要です。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/16

10.8.0.110.8.0.0/24 の範囲内にあるため、クエリは暗号化されてサーバーへ送信されます。split tunnel で公開 resolver を使用する必要がある場合は、ホストルートとして追加します: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32。これでパケットはトンネル経由になります。ただし、ローカルネットワークからは、以前のセッションを通じて選択したプロバイダーを把握される可能性があります。自分で運用する resolver を使えば、この問題を避けられます。

リゾルバーの割り当ては、手作業で構築した WireGuard と、調整されたメッシュの目に見える違いの 1 つです。これは WireGuard と Tailscale の比較 におけるトレードオフの一部でもあります。Headscale のコントロールサーバーをセルフホストすることで、鍵素材を第三者に渡さずに、この調整機能を利用できます。最後の点が懸念になる場合は、Tailscale はトラフィックを暗号化する鍵を保持しないことに注意してください。より重要な問いは、侵害された調整サーバーや盗まれた ID アカウントによって、ネットワークに何が追加され得るかです。

Failure three: Linux クライアントで resolvconf と systemd-resolved が競合する

macOS、Windows、iOS、Android のクライアントは公式アプリを通じて DNS = を適用するため、問題はほとんど発生しません。Linux では、複数ある resolver manager のどれを使用しているかを推測する必要がある shell script によって設定が適用されるため、問題が発生します。

最初の問題は明確に現れます。sudo wg-quick up wg0 は次のエラーで停止します。

resolvconf: command not found

wg-quickresolvconf を呼び出しますが、その binary がインストールされていません。systemd-resolved と通信する実装をインストールしてから、interface を再度起動します。

sudo apt install -y openresolv
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0

2 つ目の問題は気付きにくく、数時間を失う原因になります。interface は起動し、resolvectl status wg0 は正しく DNS Servers: 10.8.0.1 を表示しますが、名前解決は依然として以前の resolver に送られます。systemd-resolved は link ごとに別の resolver list を保持し、query ごとに link を選択します。いずれかの link が名前解決の default route として設定されていない場合、wireless link に search domain が設定されている一方で対象の link には設定されていないため、wireless link の resolver が使われ続けます。

resolver の設定と default route の指定を同じ手順で行います。%i は interface name に展開されるため、この block はどの interface でもそのまま使用できます。

[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %i

この方法で PostUp を使用する場合は、DNS = 行を削除します。削除しないと、2 つの mechanism が resolver state を書き込み、後から cleanup するのは一方だけになるためです。重要なのは ~. argument です。これは wg0 をすべての名前解決に対する routing domain として指定します。その結果、systemd-resolved は query ごとに link を選択せず、すべての query をそこへ送信します。設定を確認します。

resolvectl status wg0

正常な出力には DNS Servers: 10.8.0.1Default Route: yes が含まれます。Default Routeno と表示される場合、resolvectl domain の処理が実行されておらず、link selection に戻っています。

もう 1 つ、確認しておくべきケースがあります。/etc/resolv.conf/run/systemd/resolve/stub-resolv.conf への symlink ではなく実ファイルの場合、通常は NetworkManager または container runtime など、別の component がそのファイルを管理しています。他の調査を始める前に ls -l /etc/resolv.conf を実行してください。network change のたびにそのファイルを書き換える tool があると、最も都合の悪いタイミングで設定が元に戻されます。

アップグレード: トンネル経由で独自のフィルタリングリゾルバーを運用する

クエリが安定してトンネルを通るようになると、接続先のリゾルバーが制御点になります。そこに AdGuard Home を構築すると、接続中のすべてのデバイスで、クライアントソフトウェアやデバイスごとの設定なしに、ブロックリストによるフィルタリングとクエリログを利用できます。2026 年 7 月に確認した公式インストールスクリプトは、1 行で実行できます。

curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

初回起動時、セットアップウィザードは port 3000 で待ち受けます。この port を外部公開するのではなく、トンネル経由で http://10.8.0.1:3000 にアクセスしてください。ウィザードでは、DNS の listen address と管理画面の listen address の両方を 10.8.0.1 に設定します。障害 1 の unbound がまだ同じ address を使用している場合は、まず sudo systemctl disable --now unbound で停止してください。1 つの address で 2 つのプロセスが UDP port 53 に bind することはできず、後から起動したプロセスが listen udp 10.8.0.1:53: bind: address already in use で終了するためです。

クライアント設定がすでに DNS = 10.8.0.1 になっていれば、変更は不要です。これで、すべての peer からの lookup がクエリログに表示されます。ただし、これは無条件に得られる利点ではなく、実際のプライバシーに関わる判断です。信頼先をインターネットプロバイダーから自分自身へ移すことになり、そのサーバーにパッチを適用し続ける責任も自分が負うためです。インターネットに公開するサーバーでは、まず基本的な対策を整える必要があります。新しい VPS の最初の 10 分でその手順を説明しています。

FAQ

WireGuard トンネルは接続するのに、名前を解決できないのはなぜですか?

トンネルはパケットを運びますが、名前は処理しません。そのため、トンネルが動作しているのに名前解決に失敗する場合は、指定した resolver が応答していません。クライアントで dig +short @10.8.0.1 example.com を実行して確認します。communication timed out の応答は、トンネルのアドレスで待ち受ける resolver がないことを示します。systemd-resolved の stub が 127.0.0.53 にしか bind していないことが、よくある原因です。または、サーバーの firewall が wg0 に到着する UDP port 53 を破棄しています。まず待ち受けを修正し、その後、wg0 に対してのみ port を開放します。

DNS が WireGuard 経由で漏れているか確認するにはどうすればよいですか?

クライアントで sudo tcpdump -ni any -c 10 port 53 を実行し、閲覧中に interface 列を確認します。すべてのパケットが wg0 上にある必要があります。wireless または ethernet interface に表示される場合、クエリが平文で送信されています。dig +short whoami.akamai.net でも確認できます。これは、問い合わせを行った recursive resolver の public address を返すため、サーバーの address 以外が返れば漏えいが確認できます。

split tunnel を使用する場合、DNS = の行は必要ですか?

はい。resolver の address も AllowedIPs 内に含まれていなければなりません。含まれていないと、クライアントはその resolver への route を持てません。AllowedIPs = 10.8.0.0/24 を使用すると、10.8.0.1 の resolver が対象となり、クエリは暗号化されます。9.9.9.9 のような public resolver は対象外です。そのため、DNS の行が正しく見えても、クエリは local link 経由で送信されます。

resolvectl には正しい server が表示されるのに、名前解決が別の場所へ送られるのはなぜですか?

systemd-resolved は link ごとに resolver list を保持し、クエリごとに link を選択します。そのため、wg0 に正しい entry があっても、別の link が名前解決用の default route を持っていると無視されます。クライアントの [Interface] block に PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. を追加し、DNS = の行を削除します。その後、resolvectl status wg0Default Route: yes を報告するはずです。

複数のクライアントで問題が発生している場合、最初にどれを修正すべきですか?

Linux client を1台修正してください。仕組みを確認できるのは Linux client だけだからです。resolvectl statustcpdump により、どの resolver が応答し、どの interface がパケットを運んだかを確認できます。Phone と desktop のアプリは、同じ DNSAllowedIPs の値を内部で適用するため、処理の詳細は表示されません。Linux client が正しく動作すれば、検証済みの設定をそのまま適用できます。