キルスイッチはIPv4しかブロックしない:IPv6が今も抜け出す理由
IPv4向けのファイアウォールルールはIPv6について何も語らない。デュアルスタック端末では、アプリが迂回経路を保ったままトンネルだけが落ちることがある。
トンネルが落ち、キルスイッチは作動したと報告し、ダウンロードは続いている。IPv4のルールに壊れたところはない。アプリは、そのルールが決して書かれなかった経路へ移動しただけだ。
デュアルスタック端末には独立した出口が二つある。片方だけを塞ぐのは半分のブロックだ。
二つのルールセット、二つの既定値
Linuxでは、iptablesとip6tablesは別々のポリシーを持つ別々のテーブルだ。IPv4テーブルのINPUTとOUTPUTチェーンをDROPにしても、IPv6テーブルでは何も変わらない(既定値が通常ACCEPTだからだ)。同じ分裂はnftablesにもあり、一つのファミリーを調べて、自分のルールを運んでいるのが片方だけだと分かる。この非対称性は正常であり、問題の全体がそこにある。
だからこそキルスイッチは徹底して見えても部分的にしか働かないことがある。IPv4のルールを書いたスクリプトは実行され、カウンターは増え、ログ行は現れ、IPv6のパケットは物理インターフェースをまったく無傷のまま出ていく。
クライアントが実際に何をインストールするかを読むべきで、マーケティングページの約束ではない。IPv6をトンネルへ流すクライアントもあれば、意図的に遮断するものもあり、プラットフォーム側のロックダウンが別のルールを適用する間、そのまま放っておくものもある。ここで信頼に値する唯一の情報源はベンダーの文書だ。
インターフェース設定から分かること
wg-quickのマニュアルページにはIPv6のルールが例示設定に含まれており、その理由はまさにこの隙間だ。その例は飾りではない。IPv4のルールだけでは第二のファミリーを開けたままにしてしまうから存在する。
例の半分をコピーすれば、ポリシーの半分ができる。これがこの漏れの最も一般的な起源だ。あるブログ記事が長さの都合で例を削った。その削られた版が、みんなが再利用するテンプレートになった。
# what is actually installed, per family?
sudo iptables -S OUTPUT | head -20
sudo ip6tables -S OUTPUT | head -20
# nftables: inspect each family separately
sudo nft list ruleset inet | head -40
# does this host even have a usable IPv6 path?
ip -6 route show default
二つ目のコマンドが許可的なポリシーを表示し、一つ目がDROPを表示するなら、クライアントに触れずに答えは見つかっている。その非対称性がバグだ。
一つの検索で全体像は分からない理由
一つの名前がAレコードとAAAAレコードの両方を返すことがあり、アプリはすべて同じ選び方をするわけではない。ブラウザはネットワークが提供すればIPv6を優先し、失敗すれば退避することがある一方、バックグラウンド同期や更新プログラムは独自のリゾルバーと独自の優先順位を使う。したがってIPv4での成功したテストは一つの経路を証明するだけで、ポリシーを証明しない。
ネットワークの切り替えも答えを変える。別のWi-Fiネットワークに接続する、スリープから復帰する、モバイルに切り替えるといったことで端末に新しいIPv6プレフィックスが割り当てられ、オフィスのLANでは十分に見えたポリシーがそれをカバーしないことがある。
トンネルが落ちている状態をテストする
接続中のテストはトンネルが動いていることを教える。興味深いのは利用できない状態のテストで、キルスイッチが踏ん張るべきなのはそのときだ。意図的にトンネルを止め、保護しているアプリから重要な宛先を試す。
# with the tunnel stopped, does anything still leave?
ip -6 route get 2606:4700:4700::1111
curl -6 -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://ipv6.example.net/
curl -4 -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://ipv4.example.net/
両方のファミリーが閉じた状態で失敗すべきだ。IPv4の要求がタイムアウトし、IPv6の要求がステータスコードを返すなら、ポリシーは不完全であり、トンネルを何度再テストしてもそれは変わらない。
そのテストには文書化された例外も残しておく。ローカルネットワークの検出、DHCPの更新、VPNエンドポイントへのブートストラップ経路は到達可能なままである必要があるかもしれず、そうした例外は障害時に発見するのではなくポリシーに明記すべきだ。トンネルが戻れないために失敗する漏えいテストはセキュリティ上の所見ではなく、接続性の所見だ。