WireGuard を立ち上げ、トンネルは通信を通し、それでも内部名は解決しません。次の一手として WireGuard の設定に DNS 項目を探す人が多いのですが、他の VPN のように相手側からリゾルバを配れるわけではありません。配れません。ハンドシェイクが運ぶのは鍵、インターフェースアドレス、許可 IP だけで、DNS サーバーや検索ドメインのフィールドはありません。リゾルバの方針はクライアント側にあり、修正もそこに属します。

トンネルとリゾルバは別々の契約

WireGuard は意図的に小さい設計です。指定したアドレス宛のパケットを運び、ピアを認証します。その層より上はすべてあなたの設計です。OpenVPN は制御チャネルが設定を運ぶため dhcp-option DNS を配れますが、この違いが両者の移行時に人を転ばせます。

つまり動作するトンネルは名前解決について何も語りません。クライアントは 10.90.0.1 への完璧な経路を持ちながら、問い合わせを公開リゾルバへ送り続けることができ、だから「VPN が DNS を壊した」という症状に見えるのです。実際には DNS を VPN に向けたことは一度もありません。

再帰リゾルバにならずにゾーンを提供する

サーバー側は小さな権威ゾーンであり、汎用リゾルバではありません。この例ではゲートウェイが 10.90.0.1、クライアントが 10.90.0.0/24、目的のアプリケーションは 10.60.0.20 で応答します。

これらの設定は新しいブロックを作らず、既存の options ブロックへ統合してください:

options {
    listen-on { 127.0.0.1; 10.90.0.1; };
    listen-on-v6 { none; };
    allow-query { 127.0.0.1; 10.90.0.0/24; };
    allow-transfer { none; };
    recursion no;
};

次にゾーンとそのファイルを宣言します:

zone "corp.example" {
    type primary;
    file "/etc/bind/db.corp.example";
};
$TTL 300
@ IN SOA ns.corp.example. hostmaster.corp.example. ( 1 3600 600 604800 300 )
@      IN NS ns.corp.example.
ns     IN A  10.90.0.1
portal IN A  10.60.0.20

読み込み時の構文エラーは、そのサーバーが提供する全ゾーンを巻き込んで落とすため、再読み込みの前に検証してください:

named-checkconf
named-checkzone corp.example /etc/bind/db.corp.example

UDP と TCP の 53 は VPN インターフェースにだけ開けてください。公開インターフェースに非公開の権威を出すと、問い合わせも列挙も誘います。allow-transfer は、セカンダリが本当に必要とする場合を除いて閉じたままにします。

クライアントをそこへ向ける、リンクごとに

接続は NetworkManager が所有し、リゾルバは systemd-resolved だと仮定します。まず既存の方針、とくにルートルーティングドメインを読んでください。~. の項目は、これから足すものより優先されます。

nmcli connection modify wg-office +ipv4.dns 10.90.0.1
nmcli connection modify wg-office +ipv4.dns-search '~corp.example'

重要なのはチルダです。ドメインを経路専用として印し、corp.example 配下の名前はこのリンクの DNS サーバーへ送られ、ドメインは短縮名検索の接尾辞として付加されません。これがないと portal と打った時点で portal.corp.example を解決し始め、あなたには便利で他の全員には驚きになります。チルダは引用符の内側に置いてください。引用符なしでは、ホームディレクトリを指そうと待ち構えるシェル展開になります。

変更はインターフェースを所有する管理ツール経由で適用し、そのあと接続をやり直してください。同じインターフェースに二つ目の wg-quick を起動しないでください。所有者が二人いると経路を奪い合い、最悪の瞬間に片方が勝ちます。

名前より先に経路を検証する

クライアントから名前を問い合わせ、応答とそれを生成したサーバーの両方を確認します:

resolvectl query portal.corp.example

10.60.0.20 が返れば DNS の契約は果たされています。タイムアウトする場合は、まず 10.90.0.1 への経路、次にファイアウォール規則、その次にサーバーの allow-query を確認します。この構成での名前解決の失敗はほぼ常に到達性か ACL で、ゾーンファイルではありません。クライアントから外へ向かって調べてください。サーバーは問い合わせが届かなかった理由を教えてくれません。

アプリケーションには独自の経路と独自のサービス許可が今も必要です。解決済みの名前が到達不能なアドレスを指すのは、同じ服を着た別の故障です。

まだ自動化されていないこと

独自のリゾルバロジックを持つアプリケーションはシステムのリゾルバを完全に無視し、nmcli をいくら使っても変わりません。DNSSEC を検証する配備では、非公開ゾーン用に明示的なトラストアンカーの設計が必要です。検証を切れという一律の指示が答えではありません。検証はユーザーが実際に使うクライアントソフトと同じもので行い、たまたまシステムリゾルバを使う道具で済ませないでください。その差がバグ報告の全体です。

艦隊はプロビジョニングシステムでこのクライアント方針を自動化できますが、方針は所有者を持つ別のオブジェクトのままです。BIND 9 のリファレンス は上で使った待ち受けと問い合わせの制御を扱っており、導入済みのバージョンの挙動を確認するのに適した場所です。

次の一手:ゾーンのシリアル更新と確認コマンドを変更手順に加え、レコード編集が未確認のまま本番へ届かないようにしてください。

関連記事