VPNリークを直すためにIPv6を無効化する? まず方針を決めよう
リンクローカルアドレスはリークではないし、グローバルなIPv6経路も同様だ。まずブロック・経由・放置のどれかを選ぶ。
IPv6範囲のアドレスがテストページに現れ、トンネルは明らかにそれを運んでおらず、インターネットで最も人気のある助言はIPv6をどこでも無効化することだ。そのコマンドは確かにパネルを静かにする。しかしアクセスネットワークが依存しているかもしれないプロトコルも取り除き、そのアドレスが本当のリークだったのか、リンクローカルインターフェースアドレスだったのか、それとも仕事をしているリゾルバだったのかを分からないままにする。正しい制御を決めるのは三つの条件であり、ブロックに至るのはそのうち一つだけだ。
ツールが実際に何を測ったのかを特定する
最もよくある誤検知はリンクローカルアドレスで、fe80: で始まり、IPv6対応のあらゆるインターフェースに存在する。IPv6でインターネットに到達できるかどうかは関係ない。インターフェース一覧や一部のアプリ診断に現れるが、通信経路については何も語らない。
二つ目の誤検知は fc00::/7 内の一意なローカルアドレスで、これはネットワーク内部で使われるプライベート範囲だ。ホストが持つすべてのアドレスを表示するツールは、公開アドレスの隣に喜んで並べる。急いで読む人はそれをリークと呼び、存在しない問題に一時間を費やす。
三つ目は誤検知ではまったくない。トンネルの外でインターネットに到達するグローバルアドレスこそ本当のリークであり、何かを決める前に測る価値がある。
ip -6 addr show scope global
ip -6 route show default
curl -6 -sS --max-time 6 https://ifconfig.co
最初のコマンドがグローバルアドレスを表示し、三つ目がトンネルのものではない公開IPv6アドレスを返すなら、トンネルの外に実際の経路がある。最初がリンクローカル項目以外を何も表示しないなら、直すべきリークはそもそも存在しなかった。
制御を決める三つの条件
判断は「IPv6が良い」「IPv6が悪い」ではない。三つの状況のどれにいるかであり、それぞれ正解が違い、間違えたときの代償も違う。
| Situation | Correct control | Cost if you disable IPv6 instead |
|---|---|---|
| Exit has no IPv6, host does | Block IPv6 deliberately in the tunnel policy | Same visible result, no documentation of intent |
| Exit carries IPv6, host leaks | Route IPv6 into the tunnel and verify | You lose IPv6 reachability entirely |
| Access network is IPv6-only | Change nothing; use the tunnel's IPv6 | Machine loses connectivity completely |
一つ目の行は人が普通に意味するもので、正当だ。出口がIPv6をサポートしていないクライアントは、ホスト本来のIPv6通信を黙って外に出してはならない。それが文書化されたデュアルスタックのリークだからだ。要点は、それを明示された方針としてブロックすることであり、カーネルでプロトコルを無効化することではない。見える結果は同じで、後から見直せるのは片方だけだ。
三つ目の行は、一般論の助言が実際に有害になる場所だ。携帯事業者や一部の家庭回線は、IPv4宛先向けの変換を備えたIPv6専用網を運用している。そこでIPv6を外すと、その網が提供する唯一の転送手段を外すことになり、デバッグしていた障害よりはるかに悪い停止を生む。
出口にIPv6がないなら、意図してブロックする
クライアント自身の仕組みを優先する。トンネルが上がっている間だけ正確に適用され、落ちれば元に戻るからだ。OpenVPNにはそのためのオプションがあり、他のクライアントには iptables の同等のルールがある。
block-ipv6
ip6tables -A OUTPUT -o eth0 -j REJECT --reject-with ipv6-port-unreachable
指示はプロファイルに置き、ルールは見直して削除できるファイアウォールに置く。どちらも閉じた状態で失敗し、それが望ましい。そしてどちらも設定差分に現れる。起動スクリプトに埋もれたカーネルの sysctl にはそれができない。
なぜそこにあるのかを記録する。コメントのないブロックルールは、IPv6を別の用途で必要とする次の人に消され、やがてリークが静かに戻る。
出口がIPv6を運ぶなら、経路を設定して両方のファミリーを試す
サーバーが対応しているならIPv6を運ぶのが良い答えで、それほど難しくもない。要件は、トンネルインターフェースがそのファミリーのアドレスを持ち、その既定経路が物理インターフェースの外ではなくトンネルの中を指すことだ。
ip -6 route get 2606:4700:4700::1111
ip -6 route show default
curl -6 -sS --max-time 6 https://ifconfig.co
curl -4 -sS --max-time 6 https://ifconfig.co
経路の照会が決定的なテストだ。トンネルインターフェースを名指しすれば、IPv6通信は運ばれている。そのうえで二つの curl 呼び出しが各ファミリーの見え方を確かめ、両者を比べることで、両方の経路がいま同じ出口から出ていることを証明できる。
接続に成功しただけで止めてはいけない。トンネルを再接続してもう一度確認する。サーバーが初期設定でしか送らない場合、プッシュされたIPv6経路は再確立時に失われることがあるからだ。次に除外された宛先を一つ確認する。分割トンネルのルールこそ、二つのファミリーが最もよく食い違う場所だ。
アクセスネットワークがIPv6専用なら、そのままにする
ネットワークによってはIPv6だけを提供し、端末が事業者側の変換機構を通じてIPv4サービスに到達することを前提にしている。そうした機械でIPv6を無効化するのは安全保障の改善ではなく、何かへの唯一の経路を奪うことだ。誰も必要としなかったテスト結果のために自分で起こす障害である。
ここを間違えたときの症状は特徴的で不快だ。トンネルは確立したように見え、名前解決は動き、何も読み込まれない。IPv6の変更後にこれを見たら、ただちに設定を戻し、診断は別の場所で続ける。
どれを選ぶにせよ、決定をプロファイルかファイアウォールに明示し、出口が実際に何を支えるかに結びつけ、RFC 7359 のデュアルスタックに関する議論が述べるデュアルスタックの挙動を書き留める。宣言されたブロックは方針である。無効化されたプロトコルは誰も監査できない回避策であり、テストページからは同じに見える。