ネストした IPsec は、二つの層が別々のマシンで終端するときに考えやすい。四つのゲートウェイ、二本のトンネル、そして設計が機能するかを決める一つの問い: 内側トンネルがパケットの処理を終えたとき、外側トンネルは実際に何を見ているのか。これに答えれば、セレクタ、ルート、トラブルシューティングの順序が自ずと決まる。間違えれば、技術的には上がっているトンネルを一日デバッグすることになる。

四ゲートウェイのモデル

外側ゲートウェイ A と B が二つのサイト間に最初のトンネルを構築する。A の背後には通過アドレス10.60.0.2を持つ内側ゲートウェイ C が、B の背後には通過アドレス10.70.0.2を持つ内側ゲートウェイ D がいる。アプリケーションネットワークは C と D の背後にあり、例のどのアドレスも意図的に重複していない。

application net -> C -> A == outer IPsec == B -> D -> application net
                       \---------- inner IPsec ----------/

C transit: 10.60.0.2      D transit: 10.70.0.2
A and B:    underlay addresses only

層を四台のホストに分けるということは、各マシンが一つの境界を強制するということだ。両方の層を一台で動かすホストは、二組のポリシー、二つのルーティングテーブル、二つの障害モードを一台のマシンで整合させねばならず、可能ではあるが観察はずっと難しい。

各層は自分の保護だけを取り除く

C は D 宛てのアプリケーションパケットを暗号化する。結果は C から D 宛てになり、それが A に届く。下流のすべてはこの書き換えに依存する。

A はそれを B 向けに再度暗号化する。B は外側の層を復号し、C から D へのパケットを見て、暗号化されたまま転送する。D が内側の保護を取り除き、アプリケーションパケットを届ける。

つまり A と B は内側のエンドポイントとそのメタデータを見るが、アプリケーションのペイロードを復号する当事者ではない。これは設計の実際の性質であり、C、D、アプリケーションホストが信頼できるという主張ではない。

外側セレクタは内側ゲートウェイを指す

ここでこうした構成の多くが失敗する。ポリシーベースの外側トンネルでは、ネゴシエートするセレクタに A と B が実際に扱うアドレスが含まれていなければならない:10.60.0.2/32と10.70.0.2/32、正しいローカルとリモートの順序で。

最終的なアプリケーションサブネットを外側セレクタに入れても動かない。パケットが A に届くころには、内側のカプセル化が A の保護すべきものをすでに書き換えているからだ。すると外側ポリシーは何にも一致せず、トンネルはデータを運ばずに上がってしまう。

外側の許可を UDP 500 に絞ってもいけない。内側の接続には独自のデータパスがあり、ネゴシエートした内容に応じて ESP か UDP カプセル化を使うので、外側ポリシーはそのプロトコルを許可しなければならない。

各ゲートウェイでswanctl --list-sasを使って結果を確認し、子セキュリティアソシエーションが意図したアドレスを報告していること、想定したアドレスではないことを確かめる。リストにアプリケーションサブネットが出ていれば、外側ポリシーは間違った層に対して書かれている。ルーティングをデバッグする前にセレクタを直すこと。ルーティングは正常に見え、カウンタは動かないからだ。

転送と再帰の罠

セレクタはルーティングの代わりにはならない。A と B は C と D の間のトラフィックを両方向に転送する必要があり、つまり IP 転送が有効で、トンネルを指すルートがあり、反対側に戻り経路が存在していなければならない。

外側トンネルが XFRM インターフェースを使う場合、ルートはインターフェースを選び、ネゴシエートしたポリシーは依然としてそれが運ぶものを制約する。インターフェースは保護範囲を広げない。カーネルがパケットをどう拾うかが変わるだけだ。

罠は再帰だ。A から B の外側エンドポイントへのルートは、A が構築中のトンネルではなくアンダーレイに従わなければならない。そうでなければカプセル化が自分自身の中を旅しようとし、接続は決して完了しない。

層を足す前に変換を調べる

何かを調整する前に、A と B のあらゆる送信元 NAT を見る。IPsec ポリシーが適用される前に C のアドレスを書き換えるルールは、合意したセレクタを壊すことがあり、反対側で D が受け取るものを変えることもある。

広いマスカレードは層が二つあるからといって安全にはならない。遠端がどのアドレスを見るかを隠してしまい、それはトンネルが上がっていてアプリが動かないときにこそ必要な情報だ。

NAT ルールが本当に必要な場合は、各側がどのアドレスと話していると思っているかを書き留める。その一行が、トンネルと変換のどちらが原因かという議論のほとんどを解決する。一年後にルールを外すとき、次の技術者がどこを見るべきかも示す。ping ではそのどれもできない。

fail-closed を証明し、MTU を確認する

ルートが消えること自体は fail-closed ポリシーではない。別のテーブル、デフォルトルート、ポリシールールが黙ってフォールバックを提供することがあり、知る唯一の方法は外側トンネルを落としてアプリケーショントラフィックの挙動を観察することだ。事故で発見するのではなく、メンテナンス時間に意図的に行う。

三つの状態を試す: 外側トンネル停止、内側トンネル停止、両方が戻った後の復旧。各ゲートウェイでポリシーカウンタを使う。確立した IKE セッションが二つあることは、制御プレーンのネゴシエーションが成功したことを示すにすぎない。

両方のカプセル化を見込んでおく。動く IKE は小さなパケットでの結果であり、ヘッダが二つ増えるとフルサイズのアプリケーションパケットは依然として失敗しうる。数字が合うと仮定せず、実際の経路で既知のペイロードサイズを使って試すこと。計算は簡単だが、経路はそうではない。

関連記事