デュアルスタック VPN プール:strongSwan で両方のアドレスファミリーを扱う
内部の IPv4 と IPv6 プール、保護プレフィックス、外側トンネルのファミリーは三つの別々の判断です。デュアルスタックと呼ぶ前に、それぞれを設計してください。
ゲートウェイは、外側トンネルが依然として IPv4 上を流れていても、ロードウォリアに IPv4 と IPv6 の両方の仮想アドレスを渡せます。これらは独立した判断であり、一つとして扱うことが、デュアルスタック計画がたいてい崩れる地点です。クライアントの内部ファミリー、到達できる保護プレフィックス、カプセル化を運ぶトランスポートは、三つの別個の選択です。
混乱の多くは、デュアルスタックという言葉を、一箇所だけデュアルスタックな設計に当てはめることから生じます。サービスは内部でデュアルスタック、外側アドレスではシングルスタックでありながら、クライアントにとってはまったく問題なく動作できます。できないのは、偶然に動作することです。
内側に二つのファミリー、外側に一本の経路
外側の接続は UDP 上の IKE であり、クライアントがどこにいても到達可能なアドレスファミリーが一つ必要です。内部の IPv6 アドレスは IPv6 対応 ISP を必要としません。内部パケットは外側パケットの中のペイロードだからです。多くの稼働中の導入では、IPv4 のみのアップリンクを通して IPv6 プレフィックスを運んでいます。
外側の経路が実際に制約するのは、到達性と NAT トラバーサルです。ゲートウェイが IPv4 アドレスだけを広告すると、IPv6 のみのネットワーク上のクライアントは、どのプールを設定していてもまったく接続できません。外側のファミリーは、内部のアドレス計画ではなく、クライアント層から決めてください。
各ファミリーでクライアントにアドレスを与える
両方のファミリーを要求するのはクライアント側では一行の記述です。ただしゲートウェイに配るものがある場合に限ります。名前付きプールは送信元をサービスネットワークから分離し、この性質が半年後にもファイアウォール規則を読めるものにします。
pools {
pool4 { addrs = 10.90.0.0/24 }
pool6 { addrs = fd42:90::/64 }
}
connections {
private-access {
version = 2
pools = pool4, pool6
local { auth = pubkey certs = gateway.pem id = vpn.example.com }
remote { auth = pubkey cacerts = ca.pem vips = 0.0.0.0, :: }
children {
private { local_ts = 10.60.0.0/16, fd42:60::/48 remote_ts = dynamic }
}
}
}
このvips値は各ファミリーのアドレスを要求し、プールの一覧がそれらのアドレスの出どころを決めます。strongSwan の仮想 IP に関するドキュメントは複数の要求とプール割り当てを扱っており、特定のアドレスを求めるクライアントはレスポンダが覆せる優先度を述べているにすぎない、という点も含みます。クライアントが常に同じ値を受け取ると仮定したアクセス規則を作らないでください。
例をコピーするのではなく、自分専用の一意なローカルプレフィックスを生成してください。両方ともfd42::/16導入した二つの組織は、初めて相互接続したときに衝突を発見します。その診断は心地よいものではありません。
セレクタは宛先を表し、送信元を表さない
子 SA のローカルトラフィックセレクタは、ゲートウェイの背後にどの保護ネットワークがあるかを示し、リモートセレクタはクライアントが送信元として何を使えるかを表します。仮想プールのアドレスはそのポリシーの送信元側に属します。宛先一覧に入れるのは、設定のよくある誤読です。
両方のファミリーには、ゲートウェイ上の戻り経路と許可された転送が必要です。プールへの戻り経路なしにセレクタへプレフィックスを追加すると、確立はするものの一方向のトラフィックだけを通し、応答を黙って捨てるトンネルになります。セレクタはポリシーであり、ルーティングではありません。
プールとサービスプレフィックスは、アドレス計画の別々のブロックに保ってください。重なると、保護ホストに届くはずの経路がプールのアドレスに一致し、トンネルの中へ消えてしまいます。
DNS と応答経路が、完成した感じになるかを決める
リゾルバの応答は、リゾルバに到達するために使うトランスポートとは独立です。名前は A レコード、AAAA レコード、あるいはその両方を返すことができ、クライアントは自身の優先規則に従って選びます。内部サービスが AAAA レコードを公開していても、そのプレフィックスを誰もルーティングしていなければ、デュアルスタック網のクライアントはまず IPv6 経路を試し、失敗するまでそこにとどまります。その間、トンネル設定に誤りに見えるものは何もありません。
したがって、名前ごとにどのファミリーを使えるようにするかを決め、次に対応するプレフィックスがセレクタにあり戻り経路があることを確認します。これはサービスごとの判断です。両方のレコード種別を一律に公開することが、IPv4 のみで動いていたサービスが利用者の半分でタイムアウトし始める理由です。
完了と呼ぶ前に両方のファミリーを検証する
読み込まれる設定は、動作する設定ではありません。デーモンが報告する状態を読み、プールの割り当てを確認し、そのうえでクライアントが実際にインストールした経路を見てください。
swanctl --list-sas
swanctl --list-pools
ip -6 addr show scope global
ip -6 route get fd42:60::10
最初の二つのコマンドは、確立された子 SA と、まだ空きアドレスのあるプールを示すので、最初のクライアントでは動くのに十人目で失敗する計画が見えるようになります。最後の二つは、クライアントがプールからグローバル IPv6 アドレスを受け取ったか、保護プレフィックスへのトラフィックが実際どこへ行くかを示します。割り当てられたアドレスは、期待したアドレスではなく、設定したプールと比べてください。レスポンダがポリシーに従って別の値を選んだなら、経路とファイアウォール規則はそれに合っていなければなりません。
次に、ファミリーごとに保護ホストを一つ試し、両方に解決する名前を試してください。単一ファミリーの試験は、試していない計画の半分について何も教えてくれません。そして欠けている経路はたいていその半分にあります。