健全な VPN 出口が二つ、すでに実行中の長いアップロードが一つ、そして次の接続がもう一方のトンネルを使うという要件があります。これを満たす方法は二つあり、稼働中のゲートウェイで安全なのは一方だけです。デフォルトルートの切り替えは、アップロードに属するパケットも含めてすべてのパケットを動かします。計画的なドレインは新規接続の選択だけを変え、追跡済みのフローは開始した経路に残します。

出口を切り替える二つの方法

ルート切り替えは一つのコマンドで、数秒で元に戻せるため、障害時に使われます。また無差別で、既存のアップロードのパケットは突然別のトンネルから出てゆき、公開元アドレスも変換状態も別になります。

遠端が送信元アドレスでフローを追跡している場合、アップロードは認識されなくなるかもしれません。ドレインは接続ごとに一度だけ判断して保存することでこれを避け、古いアップロードは終わるまで自分の出口を保ちます。これがこの作業の価値のすべてであり、遠端は解釈すべき変化を何も見ません。すでに知っている接続に一致するパケットを受け取り続けます。

代償は複雑さで、二つのルーティングテーブル、正しいフックで動く分類器、そしてマシン上の他のすべてと調整しなければならないマークが必要です。

各出口に専用のテーブルを与える

出口ごとにルーティングテーブルを確保し、二つの選択肢に別々のマーク値またはビットを割り当てます。各テーブルには名前だけでなく役割に合ったルートが必要で、該当しない場合の意図的な失敗結果も必要です。メインテーブルへ黙って落ちる空のテーブル — こうして誰も選んでいない出口からトラフィックが出てゆきます。

ip rule add fwmark 0x10/0x10 table 101
ip rule add fwmark 0x20/0x20 table 102
ip route add default via 192.0.2.1 dev wg-a table 101
ip route add default via 198.51.100.1 dev wg-b table 102

各テーブルの末尾に blackhole ルートを追加し、一致しない検索が選んでいないデフォルトへ逃げるのではなく、大きな音で失敗するようにします。

最初のパケットで一度だけ選ぶ

接続追跡が存在した後、問題となるルート検索の前に分類します。新規の未分類 LAN 接続では出口を選び、接続状態に保存します。後続のパケットでは、ポリシールーティングが読むパケットマークに保存値を復元します。

微妙なのは「新しい」の意味です。conntrack は応答が見える前の初期パケットや再送に対しても NEW を報告できるため、その状態だけに頼る分類器はすでに行った選択を上書きし得ます。出口を割り当てる前に、その接続に出口が保存されていないことを確認してください。

nftables はパケットマークと接続マークを別々に保ち、メタ情報ガイドが両者間の明示的なコピーを文書化しています。接続マークは、ルールが一致するパケットマークにひとりでになるわけではなく、これが丁寧に書かれた分類器が効果を発揮しない最も一般的な理由です。

復元を意図した方向とトラフィックに限定し、インターネット出口のマークを戻りのパケットに適用すると、応答が LAN ではなく出口へ向かうことがあり、症状はファイアウォール問題に見える片方向接続です。ファイアウォールルールに触れる前に応答経路を読んでください。パケットはルーティングされているのであって、送信者へ戻っていないだけです。

ドレインの四つの段階

  1. A に触れずに B を準備します。ルーティング、転送、認可、NAT、戻り経路を用意し、ゲートウェイの既存の設定所有者を通じて、そのテーブルと選択ポリシーを導入します。

  2. 分類器を切り替え、新規の未分類接続が B を選ぶようにし、保存済みの選択は保持します。アトミックな nftables トランザクションは、古い状態を消す必要のある窓を避けます。

  3. A のフローが終わるまで A を稼働させます。そのインターフェース、テーブル、遠隔出口、NAT マッピングは依然としてそれらのフローの一部であり、NAT ルールを編集しても既存のバインドは再構築されません。

  4. ドレイン条件が満たされたら A を退役させ、その判断は接続状態とアプリケーションの挙動によるもので、一度静かな間隔があったからではありません。

ドレインが約束できないこと

ブラウザのリクエストは新しいトランスポート接続ではなく、プーリングは古い接続でリクエストを送り続けます。逆に、UDP フローは conntrack から老化し、後続のパケットは新規に分類されます。ドレインが追うのは追跡済みフローであり、アプリケーションのセッション観ではありません。

A のフローが終わる前に A が故障すると、保存されたマークはそれらを救いません。B 経由で再接続するか、まったく再接続しません。計画的なドレインが買うのは元の経路が健全な間の継続性であり、独立した出口間の状態複製ではありません。

両方の半分を検証する

変更前に長寿命の許可された接続を、変更後に本当に新しい接続を開始します。それぞれがどのトンネルを使い、遠端がどの公開元アドレスを見るかを確認し、戻りのトラフィックが戻ることを確かめます。

新しい選択を見せるために conntrack テーブルをフラッシュしないでください。それはドレインが保持すべき状態をまさに破壊し、制御された移行を、きれいに見えるテストを伴う障害に変えてしまいます。

関連記事