WireGuard に接続した後は、内部ドメインだけをトンネル経由の DNS で照会し、それ以外のドメインでは引き続きパブリック DNS を使用したい場合があります。systemd-resolved を使用している Linux システムでは、DNS ルーティングドメインを直接設定し、wg-quick の PostUp で自動的に適用できます。追加の DNS 転送サービスをインストールする必要はありません。

本文で使用する内部ネットワークアドレスは文書専用の範囲であり、example.com と example.net は予約済みのサンプルドメインです。導入時は、自分のアドレスとドメインに置き換えてください。

目標と適用環境

本文では次の例を使用します。

項目設定
WireGuard インターフェースwg0
トンネル内 DNS198.51.100.53
デフォルト DNS223.5.5.5
内部 DNS で照会するドメインhome.arpa、example.com、example.net およびそのサブドメイン

example.com と example.net はサンプルドメインなので、必要に応じて置き換えるか削除してください。ここで設定するのはドメインのサフィックスであり、トップレベルドメインに限られません。corp.example.com のようなサブドメインも指定できます。

適用対象は、wg-quick が WireGuard を、systemd-resolved がシステム DNS を管理する Armbian、Debian、Ubuntu です。NetworkManager などのツールが直接管理する WireGuard 接続では、これらのフックが実行されるとは限りません。対応する管理ツールの設定方法を使用してください。

まず実際の環境を確認します。

resolvectl --version
wg --version
systemctl is-active systemd-resolved
resolvectl status
ls -l /etc/resolv.conf
cat /etc/resolv.conf

/etc/resolv.conf に次の内容が含まれている場合、通常、プログラムがローカルのスタブ経由で systemd-resolved にアクセスしています。

nameserver 127.0.0.53
options edns0 trust-ad
search .

このファイルはそのまま保持し、2 つの上流 DNS に変更しないでください。nameserver が複数あるだけでは、ドメインごとの分岐を表現できません。本文では既存の DNS ルーティング機能を使用します。システムに resolvectl がない、またはサービス が実行されていない場合は、先に本機の DNS 管理方式を確認してください。

1. デフォルト DNS の設定

設定ディレクトリを作成し、ファイルを編集します。

sudo mkdir -p /etc/systemd/resolved.conf.d
sudo vim /etc/systemd/resolved.conf.d/90-split-dns.conf

次の内容を書き込みます。

[Resolve]
DNS=
DNS=223.5.5.5
FallbackDNS=
Domains=
Domains=~.

空の DNS= と Domains= は、これまでに累積されたグローバルリストを消去し、続けて本文で必要な値を設定します。FallbackDNS= はフォールバックリストを空にします。これはドメイン単位の分岐ルールではありません。

~. は、すべてのドメインに一致するルーティングドメインです。稍後に wg0 、より具体的なドメインサフィックスを設定すると、それらが優先して一致します。

sudo systemctl restart systemd-resolved

この手順で変更するのはグローバル設定であり、他の NIC の DNS ルーティングドメインは消去されません。他の NIC にすでに ~.、または同じかより具体的なドメインルールが設定されている場合は、先にその接続を管轄するネットワーク管理設定で競合を解決してください。

2. WireGuard に DNS フックを追加する

既存の設定を編集します。

sudo vim /etc/wireguard/wg0.conf

既存の [Interface] セクション内に次の内容を追加します。

PostUp = resolvectl dns %i 198.51.100.53
PostUp = resolvectl domain %i '~home.arpa' '~example.com' '~example.net'
PostUp = resolvectl default-route %i no

既存のアドレス、鍵、Peer、およびルーティング設定は保持してください。元々に DNS = ... がある場合は削除し、wg-quick が resolvconf 経由で別の一組の DNS を同時に設定しないようにしてください。重复する [Interface] セクションを新しく作成しないでください。

各行の役割は次のとおりです。

設定役割
resolvectl dns %i 198.51.100.53このインターフェースの DNS サーバーを設定します
resolvectl domain %i ...このインターフェースが担当する DNS ルーティングドメインを設定します
resolvectl default-route %i no一致しないドメインのデフォルト DNS 経路としてこのインターフェースを使用しません

wg-quick は %i を wg0 などのインターフェース名に置き換えます。複数の PostUp は設定された順序どおりに実行されます。

default-route no は DNS サーバーの選択にのみ影響し、IP のデフォルトルートは変更しません。~. のルーティングドメインを明示的に上書きすることもできません。ここでの分岐は、主にグローバルな ~. とインターフェース上の具体的なサフィックスによって実現されます。

通常どおり wg-quick down を実行すると、インターフェースが削除され、対応するリンク単位の DNS 設定も消えます。そのため、PostDown = resolvectl revert %i を追加する必要はありません。インターフェースを削除した後に revert を実行すると,反而、インターフェースが見つからない可能性があります。

DNS サーバーにはトンネル経由で到達できる必要があります。Peer の AllowedIPs が 198.51.100.53 を,包括していることを確認してください。たとえば 198.51.100.0/24 が含まれているWVrage 있습니다。必要に応じて、適切なネットワーク範囲または 198.51.100.53/32 を追加し、既存のルートを上書きしないでください。DNS で名前解決できることは_selinux…? サービスアドレスへの到達性までは保証しません。サービス用ネットワークには引き続き適切なルートが必要です。

3. トンネルを切断せずに直ちに適用する

wg0 がすでに実行中の場合は、ファイルを保存してから次を実行します。

sudo resolvectl dns wg0 198.51.100.53
sudo resolvectl domain wg0 '~home.arpa' '~example.com' '~example.net'
sudo resolvectl default-route wg0 no
sudo resolvectl flush-caches

これらのコマンドは現在の実行状態を更新し、設定ファイルの PostUp は次回起動時に自動的に設定を担当します。wg syncconf だけでは PostUp は再実行されません。

インターフェースがまだ起動していない場合は、元々の管理方法たとえば次で起動します。

sudo systemctl start wg-quick@wg0

SaveConfig = true を使用している場合、インターフェースを停止するときに実行状態の設定ファイルが上書きされる可能性があります。変更前にこのオプションを適切に設定し、設定変更が失われないようにしてください。

4. 分岐の検証

実際の設定を確認します。

resolvectl status

グローバル設定に 223.5.5.5 と ~. が、wg0 に 198.51.100.53 と指定した 3 つのルーティングドメインが表示されるはずです。

以下の内部ドメイン名を、実際に存在するレコードに置き換えてください。

resolvectl query nas.home.arpa
resolvectl query www.baidu.com

期待されるルールは次のとおりです。これは設定目標であり、実機でのテスト出力ではありません。

照会対象DNS サーバー
home.arpa、nas.home.arpa198.51.100.53
example.com、git.example.com198.51.100.53
example.net、a.b.example.net198.51.100.53
www.baidu.com223.5.5.5

実際に送信されるパケットを確認する場合は、1 つのターミナルで次を実行します。

sudo tcpdump -ni any 'port 53 and (host 198.51.100.53 or host 223.5.5.5)'

別のターミナルでキャッシュを消去してから,再度高します。直接 dig @198.51.100.53 ... を実行すると、その DNS サーバーが利用可能かどうかしか確認できず、システムの分岐ルールが有効であるとは証明できません。

ルーティングドメインの照合方法

~home.arpa は、DNS の選択にのみ使用されるルーティングドメインです。home.arpa 自身とすべてのサブドメインに一致しますが、短い名前に対して自動的にサフィックスを付加することはありません。たとえば、nas を照会しても、自動的に nas.home.arpa になるわけではありません。

短い名前の補完が本当に必要する場合は、~ を付けない home.arpa を検索ドメインとして使用できます。検索ドメインも DNS ルーティングに参加します。本文では完全なドメイン名を使用し、一貫して ~ を付けています。

systemd-resolved は、一致したラベル数が最大のものを優先します。そのため、~home.arpa は ~. より具体的です。複数のインターフェースが同じ最適な一致ドメインを持つ場合、照会が複数のインターフェースへ並行して送信される可能性があります。同じ設定を持つインターフェースを、単純なプライマリ・スタンバイ関係として解釈してはいけません。

一度のコマンドに複数のドメインを渡す場合は、スペースで区切ります。

sudo resolvectl domain wg0 '~home.arpa' '~example.com' '~example.net'

このコマンドは、インターフェースに元から設定されていたドメイン一覧を置き換えます。追記ではありません。ドメインを追加する場合は、同じコマンドですべてを記載し、PostUp も同時に変更してください。

使用上の制限とトラブルシューティング

  • インターフェースを削除すると、ルールも消えます。 トンネルを切断すると,原本はプライベートドメインだった照会が,グローバル DNS に対して行われる可能性があります。この設定は,「トンネル切断時にプライベートドメインの外部送信,禁止する」というポリシーではありません。
  • DNS の分岐とサービスのルーティングは別の問題です。 パブリック DNS を 223.5.5.5 に設定しても、その DNS サーバーへのアクセス IP トラフィックが物理 NIC を通るとは限りません。全トンネルやポリシールーティングによって、依然として WireGuard を通過する可能性があります。
  • アプリケーションはシステム DNS をバイパスする場合があります。 ブラウザに内蔵された DoH、プロキシソフトウェア独自の DNS 設定、または DNS を直接指定するプログラムは、これらのルールに従わない可能性があります。
  • プロキシによるハイジャックで,实际のパスが変化する場合があります。 sing-box の TUN やファイアウォールルールが 53 番ポートを横取りする場合,そのルールとパケットキャプチャ結果を組み合わせて確認する必要があります。
  • 実行時設定は再設定が必要になる場合があります。 systemd-resolved だけを再起動した場合や,別のネットワーク管理ツールがインターフェースの DNS を書き換えた場合は,resolvectl status を確認し,必要に応じて 3 つのコマンドを再実行してください。

解決できない場合は、まずルーティングとサービスの状態を確認します。

ip route get 198.51.100.53
resolvectl status wg0
journalctl -u systemd-resolved -n 50 --no-pager

同時に、トンネル側の DNS が待ち受けているアドレスと、ファイアウォールがクライアントからの UDP/TCP 53 クエリを許可していることを確認してください。過去に追加の DNS 転送方式を使用していた場合は、その競合設定たとえば本機の別ポートを指すグローバル DNS を先に削除してください。

参考文献

ディストリビューションごとにソフトウェアのバージョンとデフォルトのネットワークマネージャーが異なる可能性があるため、導入時は本機の man resolvectl、man resolved.conf、man wg-quick と照合してください。

補足:Debian で WireGuard を使用しない場合の DNS 分岐

内部 DNS に Debian の NIC から直接アクセスできる場合は、その NIC にルーティングドメインを設定します。以下では eno1 を例にします。

照会ドメイン上流 DNS
home.arpa、example.com およびそのサブドメイン192.0.2.53
その他のドメイン192.0.2.1

systemd-resolved のインストールと設定

まず ip route get 192.0.2.53 を実行し、出력の dev を確認します。以下の eno1 を実際のインターフェース名に置き換えてください。

Debian 12 または 13 で resolvectl: command not found と表示される場合は、systemd-resolved をインストールできます。このパッケージは /etc/resolv.conf を引き継ぐため、先に現在の設定をバックアップしてください。すでに systemd-resolved を使用している場合はインストールを省略できます。Debian 12 パッケージ情報と Debian 13 パッケージ情報も参照してください。

sudo cp -L /etc/resolv.conf /etc/resolv.conf.before-resolved
sudo apt install systemd-resolved

/etc/systemd/resolved.conf.d/ を作成し、その中の 90-split-dns.conf に次を書き込みます。

[Resolve]
DNS=
DNS=192.0.2.1
Domains=
Domains=~.

グローバル設定を適用し、現在のインターフェースの DNS ルーティングドメインを設定します。

sudo systemctl restart systemd-resolved
sudo resolvectl dns eno1 192.0.2.53
sudo resolvectl domain eno1 '~home.arpa' '~example.com'
sudo resolvectl default-route eno1 no

~home.arpa と ~example.com はグローバルな ~. より具体的であるため、優先して一致します。resolvectl status で、他のインターフェースにも同じかより具体的なルーティングドメインが設定されていないか、また eno1 に期待した内部 DNS だけがあることを確認します。

永続化と IPv6 の維持

上記の 3 つのインターフェースコマンドが変更するのは実行時状態です。systemd-networkd を使用する場合は、networkctl status eno1 で Network File を確認します。たとえばファイル名が 10-eno1.network なら、/etc/systemd/network/10-eno1.network.d/90-split-dns.conf に次を書き込みます。

[Network]
DNS=
DNS=192.0.2.53
Domains=
Domains=~home.arpa ~example.com
DNSDefaultRoute=no

[DHCPv4]
UseDNS=no
UseDomains=no

[DHCPv6]
UseDNS=no
UseDomains=no

[IPv6AcceptRA]
UseDNS=no
UseDomains=no

sudo networkctl reload を実行し、その後 resolvectl status eno1 で有効になっていることを確認します。上記の設定は、DHCP と IPv6 RA によって配布される DNS サーバーとドメインのみを絞り込みます。IPv6 アドレスとルーティングは、引き続き既存の設定によって決定されます。IPv4 アドレスの DNS サーバーも、IPv6 の AAAA レコードを返すことができます。systemd.network マニュアルも参照してください。

ifupdown を使用する場合は、/etc/network/interfaces に実際の静的アドレス、マスク、ゲートウェイを保持し、3 つの post-up を既存の iface eno1 inet static セクション内に入れてください。以下が完全な例です。

auto eno1
iface eno1 inet static
    address 192.0.2.25
    netmask 255.255.255.0
    gateway 192.0.2.1
    post-up resolvectl dns "$IFACE" 192.0.2.53
    post-up resolvectl domain "$IFACE" '~home.arpa' '~example.com'
    post-up resolvectl default-route "$IFACE" no

すでに auto eno1 または allow-hotplug eno1 がある場合は、既存の起動用宣言を保持してください。グローバルなデフォルト DNS は resolved.conf.d で設定済みなので、resolvconf フックによってインターフェース DNS が再度登録されないように、このインターフェースセクションから元の dns-nameservers 行を削除してください。gateway は IP のデフォルトルートを担当し、resolvectl default-route は DNS のデフォルト選択を制御します。

他のサービスが DHCP または RA で取得した DNS を systemd-resolved に登録している場合は、対応するサービスで自動 DNS を無効にするか設定を調整し、その後、実際に有効になっているインターフェースの DNS 一覧を確認してください。

検証

nas.home.arpa を内部ネットワークに実際に存在するレコードに置き換えてください。そのドメインに AAAA が設定されていない場合は、パブリック DNS による照会で IPv6 レコードの解決を確認し、内部ネットワークの A レコードで分岐を確認します。

resolvectl status
resolvectl query --type=A nas.home.arpa
resolvectl query --type=AAAA nas.home.arpa
resolvectl query --type=AAAA www.debian.org

送信先も確認する場合は、先に sudo resolvectl flush-caches を実行し、照会とパケットキャプチャを同時に行います。

sudo tcpdump -ni any 'port 53 and (host 192.0.2.53 or host 192.0.2.1)'