WireGuard のフルトンネル:AllowedIPs 0.0.0.0/0 だけでは足りない
0.0.0.0/0 と ::/0 はピアが何を運ぶかを選ぶだけです。クライアント管理ツール、ゲートウェイの転送、DNS、障害時の方針は依然として設定が必要です。
ピアの AllowedIPs に 0.0.0.0/0, ::/0 を書くことは誰もが覚える手順ですが、それが決めるのはピアが運んでよい通信だけです。このプレフィックスは経路を作らず、反対側で何かを転送せず、各アプリケーションのリゾルバを元の位置に置いたままにします。フルトンネルが本当にフルトンネルであるためには四つの別々のことが同時に成り立つ必要があり、後から行う確認は前の確認を救えないため下記の順に確認するのが最善です。以下の各確認はマシンから読み取れる事実であり、適用されていることを願う設定ではありません。
ピアのプレフィックスが選ぶもの、選ばないもの
AllowedIPs は選択子であると同時に許可でもあります。ローカル側にはどの宛先をこのピアへ送ってよいかを伝え、受信側にはこのピアが提示してよい送信元アドレスを伝えます。仕事はそれだけです。この説明のどこにも、ホストに経路を作る、遠端で転送を有効にする、名前解決に触れる、という要素はありません。
だからこそ 設定は完全に見えてもスプリットトンネルのように振る舞うことがあります。プレフィックスはピアがすべてを受け入れると言うだけであり、実際にそこへ何が届くかはホストの経路表が決め、外に出るかどうかはゲートウェイが決めます。これら三つの判断はどれもピアのセクションにはありません。
ピア一覧だけでなくクライアントを経路に載せる
たとえば wg-quick のような管理ツールはホストの経路表を代わりに設定するため、同じ設定ファイルでもインターフェースの立ち上げ方によって挙動が変わります。最小のプロファイルは一息で読める長さです。
[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = vpn.example.net:51820
作業を担う詳細は二つあります。まず、Address フィールドは クライアントが自分のものと考えるサブネットではなく単一のホストプレフィックスであり、既定の AllowedIPs を実際の既定経路に変えるのは管理ツールです。同じファイルを ip link と wg setconf で立ち上げると経路はまったく現れず、壊れたトンネルに見えますが実際には経路設定の手順を飛ばした健全なトンネルです。wg-quick のマニュアルは経路設定と Table の挙動を解説しています。
ファイルではなく結果を読む:ip route get 1.1.1.1 はトンネルのインターフェースを指すはずで、wg show は転送カウンタが動く最近のハンドシェイクを報告するはずです。経路のないハンドシェイクは管理ツールが一度も動いていないことを意味し、プロファイルを編集し直しても直りません。ユーザーが起動するのと同じ方法でインターフェースを立ち上げてください。そうしなければテストはデプロイではなくあなたのシェルを測ってしまいます。
エンドポイントをトンネルの外に保つ
フルトンネルは存在するために話す必要のある相手も含め、すべての宛先を捉えます。管理ツールは元のゲートウェイ経由でエンドポイントへのホスト経路を追加することで対処しており、正しい設定にほぼ必ず意図的な例外が一つ含まれるのはそのためです。設定の半分を管理ツールで、残り半分を手作業で適用することが、この例外を失う通常の道です。
エンドポイントが複数のアドレスや、運んでいないファミリーに解決するホスト名だと、例外は悪く古び、日常的に見えた再接続の後にトンネルが失敗することがあります。エンドポイントを管理下のアドレスに固定するか、管理ツールが再評価することを確認し、ネットワーク変更のたびにホスト経路を読み直してください。
同じ仕組みが、フルトンネルとキャプティブポータルが衝突する理由を説明します。ポータルは今トンネルが捉えている通信を遮断しようとするので、ホテルや空港のネットワークではポータルにログインした後にトンネルを立ち上げ、決してその前に立ち上げません。
ゲートウェイでの転送と戻り経路
ゲートウェイでは、運んでいるファミリーの転送を有効にし、翻訳するときは forward チェーンを両方向で許可し、送信元固有の検索で戻り経路を確認します。これらはいずれも成功したハンドシェイクから導かれるものではありません。ハンドシェイクは二つのピアが UDP を交換できることしか証明しないからです。カプセル化を解いたパケットがその後どうなるかについては何も述べていません。
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding
ip route get 1.1.1.1 from 10.8.0.2
検索はクライアントではなくゲートウェイで実行します。そうしなければ別の経路表を読むことになります。誤ったインターフェースを指すか、経路がないと報告するなら、クライアント側の変更ではインターネットへの出口は生まれません。ゲートウェイが出口でクライアントのアドレスを翻訳する場合、応答はその翻訳状態に依存するため、ルールはフローの送信方向だけでなく両方向に存在する必要があります。
DNS と障害時の状態を別々に試す
プロトコル自体はどのアプリケーションのリゾルバも設定しません。wg-quick は DNS 行をディストリビューションのリゾルバ統合経由で適用し、独自スタックを持つコンテナやブラウザはそれを無視することがあり、そのためトンネルがパケットを完璧に運んでいても名前解決が失敗し得ます。アドレスではなくホスト名で試し、プロファイルのサーバーが答えたと決めつけず、どのサーバーが答えたかを記録してください。
アドレスファミリーは別の答えを持つ別のテストです。v4 の既定経路は、あるアプリケーションの v6 接続がどうなるかを何も語りません。第二のファミリーを静かに漏らすトンネルは、大きな音を立てて失敗するトンネルより悪いものです。各ファミリーで名前を問い合わせ、各要求が使ったインターフェースを読み、前後で翻訳カウンタを確認してください。何にも一致しないルールは、存在しないルールとまったく同じに見えるからです。
最後に、トンネルが止まったときに望む状態を試してください。フルトンネルは、自らが担うと称する通信に対してクローズドに失敗すべきです。インターフェースが落ちてもアプリケーションが物理リンク上で静かに続くなら、その設計は手順の多いスプリットトンネルです。意図した失敗時の挙動を書き留め、意図的に確認し、最後に四つの答えを記録して終えてください。どの管理ツールがインターフェースを立ち上げるのか、どの経路が既定を運ぶのか、ゲートウェイで誰が転送し翻訳するのか、どのリゾルバが答えるのか、という四つです。