どのクライアントプロファイルもサーバーを一台だけ指定するので、利用者から見ればトンネルは一本、保護が終わる場所も一か所です。その最初のゲートウェイの後で何が起きるかはクライアントが決して見ない設計判断であり、よくある二つの設計は検査の下でまったく異なる振る舞いをします。直列チェーンでは最初のゲートウェイが復号して再暗号化します。入れ子チェーンでは外側の層を剥がし、開けない内側のトンネルを転送します。ホップ数はどちらも同じであり、だからこそ違いは数えるのではなく描く必要があります。

クライアントから始めて両端に名前を付ける

利用者が始める場所、つまり接続プロファイルから始めます。そこにはリモートアドレスが一つ、認証方式が一つ、そして設計が対応していればルート一覧が入っています。クライアントからゲートウェイAまでの外側トンネルに名前を付け、例示アドレスを与えます。クライアントのトンネルアドレス10.77.0.2、Aの10.77.0.1、そしてAの公開エンドポイント198.51.100.10で、いずれもTEST-NET-2の文書用範囲から取るので、例の中の何かが実在のホストと衝突することはありません。

そのプロファイルにはゲートウェイBへの言及がなく、それは欠陥ではありません。二番目のホップはAに属し、クライアントの唯一の義務は通信をAに届け、返ってくるものを受け取ることです。Aがトンネルを終端するのか、転送するのか、新しいものを開くのかは、この解説の残りが答える問いであり、Aが何を読めるかを決めます。

直列:Aが復号し、それから再暗号化する

直列設計ではAが通信を二回終端します。クライアントから保護を外してアプリケーションのIPパケットを取り出し、そのパケットをAがBに向けて作る二本目のトンネルで送ります。この二つの操作の間、パケットはAの転送経路の中で、プライベートな宛先に向けた普通のIPパケットとして存在します。

これには率直に言うべき二つの帰結があります。Aは内側のパケットにポリシーを適用でき、それはルート、フィルタ規則、送信元と宛先の記録という形を取ります。またAは二組の資格情報を持つ必要があり、一組はクライアントに対するサーバーとして、もう一組はBのクライアントとしてです。保護はどの瞬間にも存在しますが、保護される対象はAで身元を変えます。

そこからAがアプリケーションの平文を読むことにはなりません。クライアントとサービスがTLSを実行し、互いの証明書を検証しているとき、Aが見るのは読める要求ではなくTLSレコードの流れです。その保護がどこで終わるかを確かめるには、トンネルの図ではなくサービスの証明書チェーンを見る必要があります。

入れ子:Aは外側の層だけを剥がす

入れ子設計では、クライアントがまずBへの内側トンネルを作り、そのトンネルを外側トンネルの中に入れてAまで運びます。Aは外側のヘッダーを剥がし、内側のトンネルを見つけて、その鍵を持たないまま転送するので、内側の保護は依然としてBで終わります。

するとクライアントの上り回線は二層を運び、AとBの間の経路は一層を運びます。Aは内側トンネルの外側アドレスを見ます。それで通信が存在することと、おおよその行き先は分かりますが、ペイロードを読むには足りません。直列の場合との違いはこれだけであり、ホップカウンターには現れません。Aにまだできるのは、読めないものを転送しないことだけで、それはそのゲートウェイの事業者に常に開かれています。

入れ子はその性質の代価を払います。層が増えるたびにヘッダーのオーバーヘッドが加わるので、MTUとMSSの計画は整ったものではなく必須になり、一層で動く経路が二層では大きなパケットを静かに落とすことがあります。各層には独自の再接続とキープアライブの挙動も必要で、一方の層の障害は他方を通して部分的な停止のように見えます。

トンネルだけでなく観測者を描く

トンネルは図のやさしい部分です。設計の主題は観測者のほうなので、視点ごとに一行を書き、それぞれが実際に何を読めるかを埋めます。

Vantage pointSerial chainNested chain
Client's access networkOuter tunnel onlyOuter tunnel only
Operator of AInner IP packet between A and BOuter addresses of the inner tunnel, not its payload
Path between A and BSecond tunnelSecond tunnel
Operator of BInner packet re-originated by APayload after the inner layer is removed
Service edgeTraffic from the exit addressTraffic from the exit address

二つの行はいつも混同されます。Aの事業者と、クライアントのトンネルの提供者です。両者は同一の主体かもしれず、ゲートウェイ名が別でも独立にはなりません。独立した所有には、別々の管理制御、別々の資格情報、別々の記録が必要です。

メタデータはどちらの設計でも生き残ります。時刻、パケットサイズ、接続数は各ホップで観測可能なままで、二ホップは信号を消すのではなく相関のコストを上げます。不可視を約束する設計は、誰かがそれに頼る前にこの一覧と突き合わせるべきです。

選ぶ前に障害の経路をたどる

利用者が遭遇する順序で、クライアントから意図的に物を壊します。インターフェースとそのMTUから始めます。入れ子は認証で失敗するよりずっと早く、パケットサイズで失敗するからです。

ip -4 addr show dev tun0
ip link show dev tun0 | grep mtu
ping -M do -s 1380 -c 2 10.77.1.1

次に保護の端点を仮定せず確認します。上がっているトンネルの内側からサービスの証明書を要求し、クライアントが見るチェーンとサービスが実際に提示するチェーンを比べます。再署名や傍受をするゲートウェイはその証明書を変えるので、検査は一つのコマンドで見えるようになります。

openssl s_client -connect intranet.example.com:443 -brief < /dev/null

最後に再接続のマトリクスです。クライアントのトンネルが落ちる、Bのトンネルが落ちる、AとBの間の経路が変わる。何が戻り何が戻らないか、内側の接続が意図した搬送路の外のルートに落ちることがあるかを見ます。各試験が使ったアドレスを記録します(別のアクセス網で繰り返せば別の問いに答えることになるからです)。再接続のたびにMTUの検査も繰り返します。経路が変われば、設定行が一行も動かなくても使えるサイズが下がることがあるからです。

Aが内側のパケットにポリシーを適用する必要があるとき、またはクライアントが二本の積み重ねトンネルを動かせないときは直列を選びます。内側のペイロードがAで読めないままでなければならないときは入れ子を選びます。選択を観測者とMTUの数値とともに書き留めれば、次の人は一つの問いに答えるために図全体を描き直さずに済みます。

関連記事