一つのプライベートサブネットで機能する strongSwan 接続は、誰かが 一行編集しただけではインターネットトラフィックを運びません。フルトンネルとは、child SA がどのアドレスを保護するかについての 二つのピア間の合意であり、各ピアは相手側を自分を基準に呼びます。片側を正しく、もう片側を誤って設定すると、child SA は起動しないか、意図より狭く起動します。以下の五つの確認は、その合意をクライアントからゲートウェイを経てインターネットまでたどります。

まずクライアントのセレクターを確認する

クライアントは、遠端で保護したいものを remote_ts として記述し、送信するものはすべて自分の割り当てアドレスを起点にします。インターネットトラフィックの場合、その値はユーザーが実際に到達する宛先をカバーする必要があり、実際には IPv4 空間全体を意味します。それでも 一つのサブネットを列挙しているクライアントは、インターフェース上のプロファイル名が何であれ、分割トンネルを求めています。送信元側は通常 dynamic で、アドレスが接続時に割り当てられるためです。そこに固定の送信元を書くと、アドレスプールが変わった時点で壊れます。

children {
    net {
        local_ts  = dynamic
        remote_ts = 0.0.0.0/0
    }
}

この断片は完全な接続ファイルではなく、認証、ID、仮想アドレスプールがすでに設定されていることを前提としています。クライアントの送信元セレクターとサーバーが割り当てるアドレスは依然として一致している必要があり、そうでなければ child SA はどちらの側も予期しない範囲で起動します。swanctl --load-all でロードし、成功を想定する前に出力を読んでください。パースできるファイルでも、ピアの提案と重ならないセレクターのために拒否されることがあります。

ゲートウェイ自身の側のセレクターを確認する

ゲートウェイは同じ概念を逆方向から読みます。インターネットの宛先はゲートウェイにとってローカルなので、その local_ts が広い側であり、remote_ts がクライアントプールを表します。この反転はフルトンネル設定で最も多い間違いであり、二行がそれぞれ単独ではもっともらしく見えるためレビューを通ってしまいます。

children {
    rw {
        local_ts  = 0.0.0.0/0
        remote_ts = 10.77.0.0/24
    }
}

クライアントの断片をゲートウェイのファイルにコピーすると、どちらの側も同じ役割を主張するため、何も有用なことを表さないセレクターの組ができます。strongSwan の転送ガイドはクライアントとゲートウェイの組み合わせを明示しており、障害の後ではなく接続ファイルのそばで読む価値があります。ゲートウェイのファイルには、remote_ts が参照するプールの定義も必要です。存在しないプールを名指すセレクターは文句もなくロードされ、接続時に失敗します。

従来の ipsec.conf は左右の役割に異なるキーを使い、rightsubnet 行は swanctl の値の直接の置き換えではありません。二つの構文は、片方をもう片方に貼り付けるのではなく別々のファイルに保ってください。同じディレクトリで混ぜると、動作していた接続が再起動後に静かに元へ戻ります。

ネゴシエートされた child SA を確認し、ファイルは見ない

保存された設定は意図を証明するだけで、それ以上ではありません。ピアは要求された範囲を狭めることができ、既存の child SA はその下のファイルが変わっただけでは置き換わりません。他の何かを変える前に、実際に何がインストールされているかを確認してください。

swanctl --list-conns
swanctl --list-sas
ip xfrm policy list

最初のコマンドはデーモンが読み込んだ内容を、二番目は確立した child SA を、三番目はカーネルが適用するポリシーを示します。ファイルが 0.0.0.0/0 と言い、一覧が一つのサブネットを示すなら、ネゴシエーションが範囲を狭めたのであり、ファイルを読み直しても説明になりません。child を終了し、再開始し、三つの出力をもう一度比べてください。同じ狭い範囲で戻ってくる child は、ローカルファイルではなく相手側によって狭められており、それはローカル編集ではなく相手の管理者との会話です。

ポリシー一覧の両方向を読んでください — 片方向だけをインストールするトンネルは設定の衣装を着たルーティング問題です。往路と復路のポリシーは同じセレクターの組を鏡像で名指すべきで、鏡像の欠落はセレクターのテキストではなくデーモンか提案の欠陥です。

転送と戻り経路を確認する

セレクターはトラフィックをゲートウェイへ通しますが、ゲートウェイにそのトラフィックを先へルーティングさせはしません。転送を有効にし、ファイアウォールがフローを許可し、応答がクライアントプールへ戻る道を見つける必要があります。これは三つの別々の要件で、それぞれ違う症状で失敗します。転送ルールが欠けるとブラックホールのように振る舞い、戻りルートが欠けると一方通行のトンネルのように振る舞います。

sysctl net.ipv4.ip_forward
iptables -t nat -S | grep -i masq
ip route get 1.1.1.1

プライベートなクライアントアドレスは通常、パブリックインターフェースを出る前に意図的な送信元変換を必要とし、明示的にルーティングされた割り当ては別の扱いが必要です。NAT が関与する場合は、実装がサポートする例外を保ち、セキュリティポリシーが検査すべきトラフィックがそれを迂回して変換されないようにしてください。別のゲートウェイからコピーした広い masquerade ルールは、作者が意図したよりはるかに多くのフローを変えます。ルールはクライアントプール専用に書き、なぜ存在するのかをコメントで残してください。

クライアントでは、想定したルートではなくバックエンドがインストールしたルートを確認してください。ルートインストールが無効なマネージャーは手作業で維持するルーティング設計を必要とし、その設計はトンネルが変わるたびに更新しなければなりません。ルーティングテーブルは再接続後に確認し、新しい起動後だけに限りません。

トンネルがまだカバーしていないものを確認する

セレクターの組がカバーするのは IPv4 だけで、それ以外はありません。IPv6、DNS、アプリケーションレベルのポリシーは別々の決定であり、広い IPv4 セレクターはそれらを静かに無視します。すべての IPv4 パケットを運ぶトンネルでも、あらゆる名前解決を漏らす可能性があります。

ローカルリゾルバーで名前を解決し続けるフルトンネルはクエリをトンネル外へ漏らしプライベート名を壊すため、意図した DNS 経路を明示してください。クライアントに IPv6 アドレスが割り当てられる場合、そのアドレスファミリーにも同じ扱いが必要で、そうでなければホストはトンネルが保護しない経路を優先します。プライベート側だけが答えられる名前でテストし、パブリックな応答は漏えいとして扱ってください。

resolvectl query intranet.example.internal
traceroute -n 1.1.1.1

上の一覧からネゴシエートされたセレクターとともに、この二つのコマンドで連鎖を確認してください。traceroute が最初のホップとしてローカルルーターを示すなら、セレクターが何を主張してもトラフィックはトンネルを使っていません。インターネットアクセスが完全になるのは、選ばれたトラフィックが設計されたゲートウェイを通って許可され、転送され、戻ってきたときだけです。プロファイルに 0.0.0.0/0 を見つけることは、その連鎖の証明ではなく始まりです。

関連記事