最初のセッションが勝つ:追い出しの前に OpenVPN ログインを制限する
後からのログインを拒否することは、古いものを置き換えることとは違う。判断は同名の追い出しより前に下す必要があり、スロットの確認はアトミックでなければならない。
アカウントごとに一つのセッションを許す方針は、二回目のログインが来るまで決着したように見える。結果は二通りある。新しい接続が既存のセッションを置き換えるか、既存のセッションがスロットを保って新しい接続が拒否されるかだ。最初のセッションが勝つ方針と言えるのは後者だけである。多くの人が手を伸ばすクライアント設定は同時接続を有効にするので、この結果にはならない。
一つの設定の裏に二つの契約が隠れている
同時接続を無効にすると、同じ証明書名を持つ二つ目の接続が稼働中のセッションを押しのけることがある。同時接続を有効にすると複数のセッションを同時に許すことになり、制限とは正反対である。どちらの状態も拒否の方針ではないので、判断はまったく別の場所で下す必要がある。
何かを実装する前に契約を書き出す。誰を拒否するのか、稼働中のセッションを何で識別するのか、きれいな切断なしにセッションが死んだらどうするのか。この言葉で誰も明文化していない方針は、後から検証できない。
追い出しは接続フックより先に起きる
2.6 のサーバーコード経路では、同時接続が無効のとき、新しいクライアントの初期設定が同名の既存インスタンスを削除する。この削除は接続ハンドラの連鎖が走る前に起きる。したがって重複に気づいて失敗を返すスクリプトは、稼働中のセッションがすでに落とされた後に新しい接続を拒否することになり、まさに方針が防ごうとした結果になる。上流実装のコールバック順序だけが、あなたのビルドにとって信頼できる答えだ。
| Stage | Who can still refuse | Effect on the incumbent |
|---|---|---|
| Certificate check | Server trust configuration | None |
| Authentication decision | The authentication controller | None, because establishment has not run |
| Connect handler | A profile script | Already evicted in the same-name case |
| Post-establishment | Status tooling, monitoring | Both sessions already exist or one is gone |
状態ファイルをポーリングするのもゲートではない。同時に届いた二つの試行は、どちらも確定する前に空きスロットを見て、両方が進んでしまう。
判断を認証へ移す
証明書の検証後、管理インターフェースが認証の判断を引き受けることができる。この構成ではコントローラーは監視役ではない。接続する各クライアントインスタンスを受け取り、そのインスタンスが進んでよいかを答える。答えは確立より前に届くので、拒否しても稼働中のセッションはそのまま残る。同じチャネルが切断を報告し、コントローラーはスロットが正当に解放されたことを知る。
新しいインスタンスはすべてこのゲートを通らなければならない。再接続も、プロンプトなしで再認証する経路も含む。一部のインスタンスが決して到達しないゲートは何も守らず、その抜けは誰かが迂回路を試すまで見えないままになる。
トークンはゲートを素通りできる
トークンが発行されると、サーバーはそれを内部で検証し、その接続では外部認証を省略できる。管理呼び出しは決して起きないので、そこだけに実装したスロット確認は新しいインスタンスを見ない。この挙動は利用者には便利で、同時接続の方針には穴になる。トークン認証の接続にも同等の権威ある確認を通すか、すべての接続で判断を求める方針ならトークン経路を無効にする。
すべてのトークンを無条件に受け入れて穴埋めしてはならない。期限切れや無効なトークンは依然として失敗すべきであり、ほかのすべてと同じ判断点で失敗しなければならない。
予約はアドレスではなくインスタンスに結びつける
アドレスは弱い身元だ。同じノートパソコンからの再接続が別のアドレスから来ることも、コピーした資格情報が同じアドレスから来ることもある。予約はサーバーが割り当てるクライアントインスタンスに結びつけ、すでに受け入れたインスタンスの再認証を所有者として認識できるようにする。新しいインスタンス識別子は、同じトークンを提示しても先着優先の判断で自分のスロットを獲得しなければならない。
失敗した試行に属する予約だけを解放する。古い試行からの遅れた切断イベントが新しい所有者のスロットを消してはならない。だから解放はアカウントではなくインスタンスを名指しする。コントローラーの再起動後は、誰かを受け入れる前に稼働中のセッションを突き合わせ、アカウントを提供するすべてのゲートウェイに同じ規則を適用する。
本当に古くなったスロットをどう回復するかは別に決める。管理者にはそれを消す文書化された手段が必要であり、その経路は再接続をクリックするだけの利用者からは届かないようにすべきだ。
重要な組み合わせを試す。ほぼ同時の二つのログイン、きれいな切断後の再接続、稼働中のセッションの再認証、拒否された新規接続、コントローラーの再起動である。どの場合でも稼働中のセッションは使えるままでなければならず、新規接続は他のアカウントに巻き添えを出さずに拒否されなければならない。