hook スクリプトが起動し、ppp0 を読み、その時点でその名前を持つインターフェースに経路を適用する。それが意図したトンネルであることもあれば、一分前に接続したセッションであることもある。次の再接続で番号は移動し、同じスクリプトが黙って誤ったリンクを構成してしまう。修正は、たった今実行された呼び出しからインターフェースを取得し、意図したプロファイルをそれと一緒に持ち運ぶことだ。

オプションから hook まで一つのセッションを追う

セッションが作られる場所から始める。xl2tpd はそのトンネルの pppoptfile が示すオプションファイルで pppd を起動するので、プラグイン、ユニット番号、プロファイルマーカーはグローバルファイルではなくそこで決まる。接続マネージャが独自のオプションを生成することもあるため、/etc/ppp/options を編集したことは、対象のトンネルが変わった証拠にはならない。リンクが上がると、pppd はディストリビューションのディスパッチャから通知スクリプトを実行する。それらのスクリプトは、インターフェース名を第一引数として、プロファイルマーカーを第六引数として受け取る。

環境は同じ事実を IFNAME や PPP_IPPARAM といった名前で運ぶが、その可用性はインストールされたディスパッチャに依存する。変数に頼る前にディスパッチャを読み、上流の引数順を保つものとスクリプトを呼ぶ前に環境を濾過するものがあることを確かめること。$1 と第六引数だけを使うスクリプトは、どちらの方式でも動く。

呼び出しからインターフェースを読む

従来の hook はインターフェースを最初に受け取る。その位置値が、スクリプトを起動したセッションを表すインターフェース識別子である。先頭で変数に格納し、その変数を経路、ファイアウォール規則、後片付けに使う。

ipparam office-vpn

プロファイルマーカーはオプションが定義される場所に付け、スクリプトには付けない。トンネルのオプションファイルにその行があれば、そのファイルから作られるすべてのセッションが第六引数として office-vpn を持つ。スクリプトはマーカーで分岐しつつ、実際のインターフェースに対して動作できる。マーカーは安定しインターフェースはセッションごとに割り当てられるので、両者はコード上で分けておくこと。

拒否が正しいときだけ名前を要求する

固定名は引数を読むより簡単に見えるが、失敗時の挙動が変わる。unit オプションは外向き接続に番号を要求し、そのユニットがすでに使用中なら pppd は動的割り当てに戻る。その結果のどこにも、プロファイルのために ppp0 を予約するものはない。

ifname ppp-office

ifname オプションは挙動が異なり、要求した名前がすでに使われているか割り当てできない場合、pppd は別名を選ばずに終了する。それは外観上の改名ではなく、ポリシーの選択である。同じプロファイルの二つ目の同時インスタンスを拒否すべきときに使い、インストール済みの pppd と接続マネージャがそのオプションを通すことを確認する。

いずれにせよ、スクリプトが見る名前こそが操作対象である。設定された名前は、再起動したセッションが前回と違う名前を示すことがあるため、呼び出しを読む必要性をなくさない。

後片付けを設定したセッションに合わせる

経路とファイアウォール規則は、それを作ったスクリプトより長く残るので、後片付けはセッションが所有するオブジェクトだけを正確に削除しなければならない。規則にはインターフェースだけでなくプロファイルマーカーでもタグを付け、そのタグで削除する。二つのトンネルが同時に上がりうるなら、ppp に言及するものをすべて消すのは、片方の切断がもう片方の接続を壊すやり方だ。

バグを露呈するケースとして、一つ目がまだ接続している間に二つ目の PPP セッションを上げ、そのあと一つ目を再接続して hook がどのインターフェースを報告するかを見る。セッション一つでの成功は、名前の割り当てについて何も証明しない。VPN を停止した状態でも繰り返し、後片付けが古い経路を残さないことを確かめる。

マーカー、インターフェース、hook のパスを配備メモに残す。再起動後に番号が変わったとき、その三つの値が、設定を一切編集せずにスクリプトの挙動が変わった理由を説明する。

関連記事