VPN 経由でプライベートプレフィックスに到達するのは、期間のある要件です。その接続が利用可能な間は成立し、接続が終われば終わります。ログインスクリプトではこれを表現できません。ログインとトンネルの立ち上がりは別の瞬間であり、ログイン時に存在するトンネルが 一分後に通信を運ぶトンネルとは限らないからです。最初の判断は、どのコマンドを実行するかではありません。どのコンポーネントがプレフィックスを所有するかです。

プレフィックスには所有者が必要で、瞬間ではない

要件を主語のある文として書くことから始めます。到達するのは 10.77.0.0/24 オフィス VPN 経由で、その接続が上がっている間です。この文はプレフィックス、接続、条件を名指しし、二つのよくある代替を即座に排除します。ログインフックと、次のようなインターフェース名です。 ppp0 または utun2。

インターフェース名は実行時に割り当てられ、再接続をまたいで安定しません。先週見た名前と一致するフックは、発火しないか、他人のインターフェースに対して発火します。どちらの結果も、古い前提そのものではなくルーティングの不具合に見えます。同じ反論は、特定のトンネルが上がっている間だけ存在する名前に依存するあらゆるスクリプトに当てはまります。

サポートされたルート意図の情報源を使う

ゲートウェイ、管理プロファイル、または所有するクライアントの文書化されたルート機構が、その機構で要件を表現できるなら適切な場所です。どれが当てはまるかはプロトコルとプロバイダーに依存し、鍵は相互に流用できないため、ある値が OpenVPN プロファイルを設定しても、ネイティブの L2TP や IKEv2 クライアントについては何もわかりません。

MechanismCan carry extra prefixesWho owns the lifetime
Gateway-pushed routesOften, if the gateway is configured for itThe connection
Managed profile settingsDepends on the client and profile formatThe profile
Provider tunnel settingsYes, as included and excluded routesThe provider process
Manual commandYes, onceNobody

パケットトンネルの開発者向けに、Apple の IPv4 トンネル設定は包含ルートと除外ルートを明示的に公開しており、IPv6 にも対応するものがあります。これらはプロバイダーが使う API であり、すべてのネイティブ VPN パネルが管理者に任意のルート一覧を提供する証拠ではありません。現在の組み合わせで必要なプレフィックスを表現できないなら、次の一歩は事業者が提供するサポートされた設定経路であり、より良く振る舞うことを期待して入れる別のアプリではありません。

ライフタイムには後片付けが含まれる

外部ヘルパーが本当に必要な場合があり、そのとき「ルートを追加する」は仕事のごく一部です。どの接続に仕え、その接続がどのインターフェースを使っているかを知り、関連するネットワーク状態が落ち着くまで待ち、 続けて二回実行しても冪等のままでいる、そして自分が入れたもの以外は片付けないことが必要です。

最後の条件が痛いところです。オフィスのプレフィックスに一致するすべてのルートを削除するヘルパーは、遅かれ早かれ自分が追加していないルートも削除します。その結果の障害は VPN クライアントのせいにされます。ユーザーに見えるのがクライアントだからです。ヘルパーが何を所有するかを書く前に決めておくほうが、後からローカルサブネットが応答しなくなった理由を説明するより安く済みます。

再接続の競合

速い再接続を考えてみます。セッション A が落ち、セッション B が上がって自分のルートを入れ、そのあとで A の遅延した後片付けがようやく走ります。その後片付けがプレフィックスでルートを消すなら、B の有効な状態も一緒に消え、一秒前まで動いていた接続は何もない場所へルーティングされます。

これは所有権の競合であり、スクリプトに sleep を足してもどちらが勝つかが変わるだけです。修正は後片付けを同一性に条件付けることです。ヘルパーが入れたインターフェースとセッションを、まだ有効なものと比較し、一致したときだけ削除します。

何をテストするか、ルートにできないこと

受け入れでは四つの遷移を覆う必要があります。最初の接続、別のインターフェースへの再接続、失敗する接続試行、そして最後の切断です。それぞれの後に、遠端のアドレスに対してシステムが実際に選んだルートを読み、期待したルートを読まないこと。

route -n get 10.77.0.5
netstat -rn -f inet

厄介なケースも同じ回に含めます。必要な場所での IPv6、遠端のプレフィックスと重なるローカルプレフィックス、そしてトンネルが上がっている間も動き続けなければならない公開 VPN エンドポイント自体へのルートです。そのうえで、ルートではないものを書き出します。ルートはパケットを選ぶだけで、遠端での許可を与えず、戻り経路も作りません。それらは別の所有者を持つ別の要件のままです。

望む結果は、書いたマシンで一度たまたま成功したコマンドではなく、あらゆる遷移を通じてサポートされた接続の所有者に従うプレフィックスです。

関連記事