WireGuard のハンドシェイクは通るのにインターネットに出られない:パケットを追う
ハンドシェイクが証明するのは鍵と到達性だけです。AllowedIPs から転送、NAT、戻り経路まで 一つのパケットを追い、どこで止まるかを見ます。
トンネルは起動していて、wg show は直近のハンドシェイクを報告し、サーバーのトンネルアドレスには ping が通るのに、その先は何も応答しません。そこで鍵を作り直したり設定を共有し直したりしたくなります。しかしそれは、すでに動作が証明されている経路の部分を変えるだけです。
完了したハンドシェイクが示すのは、両ピアが鍵で合意したこと、UDP がエンドポイントに届くこと、暗号ルーティングがパケットを受け入れることです。その後にパケットがサーバーを出られるかどうかは何も示しません。
だから推測せずに 一つのパケットを追います。パケットが死ぬ場所は 四つあり、それぞれ違う痕跡を残します。
ハンドシェイクが実際に証明すること
WireGuard は Noise ハンドシェイクでセッションを確立し、その後にピア宛てのパケットを暗号化する UDP プロトコルです。wg show が数秒前のハンドシェイクと増え続ける転送カウンターを表示していれば、エンドポイント、鍵、ピアの公開鍵はすべて正しいと言えます。
証明されないのは、クライアントがインターネット向けの通信をそもそもインターフェースに入れているか、サーバーがそれを転送する意思があるか、応答が戻り道を見つけられるかです。これらはカーネルのルーティングとファイアウォールの判断であり、トンネルの外で決まります。
サーバーのトンネルアドレスへの ping がこれほど紛らわしいテストになるのはそのためです。そのパケットは サーバー自身宛て ので、ローカルで終わります。転送も、変換も、インターネットからの戻り経路も一切必要としません。
AllowedIPs はルーティングの判断です
クライアント側では AllowedIPs が 二つの役割を担います。どの宛先アドレスをこのピアのトンネルに入れるかを決める暗号鍵ルーティングテーブルであり、同時にピアがあなたから受け入れる送信元アドレスの一覧です。クライアント設定に 10.8.0.0/24 しか書かれていなければ、公開宛先はインターフェースに入らず、通常のデフォルトルートがトンネルの外へ運びます。その場合トンネルは完璧に動き、望んだことは何も行いません。
設定ファイルの記述ではなく、クライアントが実際に何を入れたかを見ます:
wg show wg0 allowed-ipsip route get 1.1.1.1
決め手は 二つ目のコマンドです。答えが物理インターフェースと通常のゲートウェイを示すなら、パケットはトンネルを通っておらず、サーバー側の変更では直りません。IPv4 用に 0.0.0.0/0 を、IPv6 用に ::/0 を別々に追加します。片方のアドレスファミリーだけを全部捕まえる規則は、もう片方を元の経路に残し、これが IPv4 のトンネルが動き IPv6 の解決が止まるよくある原因です。
ゲートウェイ上でパケットが死ぬ場所
経路が正しいのにパケットがどこにも行かないなら、パケットはサーバーに届いてそこで止まっています。四つの確認でほとんどのゲートウェイを押さえられます。
転送。 sysctl net.ipv4.ip_forward が 0 を返すのが典型的な答えで、多くのディストリビューションは今も既定で 0 です。1 にする必要があり、再起動で消えるコマンドではなく sysctl ファイルで永続的に設定します。IPv6 の転送は別のスイッチです。
フィルターのポリシー。 既定が drop の FORWARD チェーンは、トンネル経由の通信を捨てる一方でホスト自身への通信は通します。これは症状と完全に一致します。保存されたファイルではなく、稼働中のルールセットを読みます:nft list ruleset か iptables -S です。
変換かルーティングか。 プライベートなトンネルアドレスを使うクライアントには、サーバーの出口インターフェースでの送信元 NAT か、上位ネットワークが戻し方を知っているルーティング済みプレフィックスのどちらかが必要です。どちらを選ぶかはアドレス計画に従います。すでにプレフィックスを戻しているネットワークに MASQUERADE を足すのは無害ですが無意味で、経路が存在しない場所で省くと、応答はルーティングできないプライベート範囲宛てのまま残ります。
戻り経路。 ルーティング構成では、上位ルーターがあなたのサーバーを指す経路を必要とします。プロバイダーのネットワークもこれを遮断できます。いくつかのクラウドはインスタンスで送信元と宛先のチェックを有効にしており、送信元がインスタンス自身のアドレスでないパケットを、そのチェックを無効にするまで黙って捨てます。
DNS はルーティングとは違う形で失敗します
既知のアドレスへのパケットと名前解決は別々の失敗であり、エラーメッセージは逆方向に誤導します。ping 1.1.1.1 が通りブラウザーが何も読み込めないなら、経路は正常で名前解決が異常です。ping 自体が失敗するなら DNS は無関係で、前の節に戻ります。
wg-quick は設定の DNS = 行からリゾルバーを設定でき、systemd-resolved はリンクごとに独自の振る舞いをします。トンネル内でしか到達できないアドレスでリゾルバーを上書きする VPN は、トンネルが落ちた瞬間にすべての名前解決を失敗させ、トンネルがインターネットを壊したように見えます。
| Symptom | Layer to inspect |
|---|---|
| Tunnel address pings, nothing else does | Client route, then gateway forwarding |
| Public IP pings, hostnames fail | Resolver selection and reachability |
| Handshake completes, no reply ever | FORWARD policy or missing NAT on the server |
| Small requests work, large transfers stall | MTU and TCP MSS clamping |
証拠が残る順番
まずクライアント側の確認を実行します。コマンド一つで可能性の半分が消えるからです。次にサーバーがそもそもインターネットの出口なのかを確かめ、プライベートアクセス用に作られたゲートウェイは、公開宛先が通らなくても壊れてはいません。
サーバー側では、クライアントから ping を送りながらインターフェースを見ます。tcpdump -ni wg0 icmp が要求を示し、tcpdump -ni eth0 icmp がそれが外へ出ることを、変換の有無にかかわらず示すはずです。前者に出て後者に一度も出ないなら、停止はサーバー内で起きています。外に出て応答が戻らないなら、問題は上流にあり、それは別の話です。
最後に、修正が再起動後も残るようにします。転送は sysctl ファイルに、ファイアウォール規則はそれを読み込むサービスに、クライアントの経路はインターフェースを立ち上げる設定に属し、忘れてしまうシェルに置くべきではありません。再接続して同じ二つのテストを繰り返し、カウンターが動くことを確認します。