VPN後の処理はif-upではなくディスパッチャーから実行する
古いインターフェースフックはVPN接続を認識できない。vpn-upをプロファイルのUUIDで照合し、処理を再実行可能にし、決して発火しない切断に備える。
VPNが起動した後に実行すべきスクリプトには、接続を所有するコンポーネントからのイベントが必要である。古いネットワークフックのディレクトリに置いたファイルは、NetworkManager、pppd、あるいは独立したOpenVPNプロセスが作る可能性のあるあらゆるVPNに対するコールバックではない。これらの所有者はそれぞれ異なる環境で異なるイベントを報告するため、フックを選ぶ前に所有者を特定しなければならない。さもなければスクリプトは正しいのに決して動かない。
NetworkManagerが管理するVPNでは、ディスパッチャーが適切な場所であり、vpn-upが適切なアクションである。
インターフェースのイベントではなくvpn-upを使う
ディスパッチャーはupとvpn-upを区別する。前者は有効化されたインターフェースを報告し、後者は有効化されたVPN接続を報告する。Wi-Fiが上がったことは下位のリンクが存在するというだけであり、トンネルはまだ交渉中かもしれず、認証に至らないこともある。
スクリプトはインターフェースとアクションを受け取り、接続の詳細はプロファイルのUUIDやVPNのIPインターフェースも含めて環境を通じて届く。デバイス名から身元を推測するのではなく、これらの変数を読むべきである。
照合は一つの接続に限定する
接続のUUID、またはディスパッチャーが提供する別の識別子で照合し、tunの接頭辞やppp0で照合してはならない。インターフェース名は安定せず、同時に複数のトンネルが存在しうるうえ、二つのプロファイルが同じ表示名を持つこともある。tunの接頭辞で照合すると、誰も触れるつもりのなかった接続でスクリプトがいつか発火する。再接続でデバイスが作り直されると、一つのプロファイルで二回発火することもある。
処理を冪等にする。呼び出しのたびにルートを追加するコールバックは、いずれテーブルを重複で埋め尽くし、ルーティングを壊すのは二つ目のコピーである。
有効化が証明しないことを知る
vpn-pre-upはNetworkManagerがVPNの完全な有効化を報告する前に実行され、マネージャーはそれらのスクリプトを待つ。遅い検査は他のあらゆるコンポーネントが待っている有効化を遅らせるため、ブロッキング段階は処理が本当にそこに属する場合にだけ使う。
ルートが存在することは、アプリケーションが待ち受けていること、プライベート名が解決すること、ユーザーセッションが存在することを証明しない。これらは限定されたタイムアウトで別々に確認し、チェーン全体を再試行するのではなく、どの層が失敗したかを報告する。
スクリプトが動く文脈を尊重する
ディスパッチャーのスクリプトはrootとして、どのユーザーセッションの外でも実行される。ログイン中のユーザーの環境、グラフィカルセッション、解錠済みのキーリングが利用できると仮定してはならない。デスクトップの文脈がないことに、あらゆる資格情報をあらゆるプロセスから読めるようにして応じるべきではない。ユーザーセッションの作業は、コールバックがユーザーを装わずに信号を送れるユーザーサービスかセッションヘルパーに置く。
スクリプトの所有権と権限も重要である。rootで実行され、どのユーザーでも置き換えられるファイルは権限昇格の経路であり、VPNのロジックが正しいかどうかとは独立した所見である。
決して発火しない切断に備える
NetworkManagerは、予期しない終了や接続喪失のような強制切断ではvpn-pre-downが発行されないと記録している。したがって、穏やかなpre-downだけを前提にした後始末は、構造上不完全である。スクリプトが変更する共有状態には、クラッシュ後に復元できる別の所有者が必要であり、その復旧経路は仮定せずに試験しなければならない。
通常の接続、再接続、意図的な切断、ケーブルの引き抜きでフックを試す。秘密情報を記録せずに、発火したUUID、アクション、インターフェースを記録する。その記録だけが、意図した接続でフックが動いたことを示す信頼できる証拠であり、次の変更を安全にするのはそれである。