OpenVPN で persist-tun と persist-key が実際に何を生き延びさせるか
どちらのオプションも、生きているプロセス内でのソフトリセットを対象にしています。停止後にインターフェースを保持するものではなく、通信を遮断するポリシーでもありません。
サービスを停止すると、persist-tun が設定されていてもインターフェースは削除されます。これはオプションが文書どおりに動作しているのであって、失敗ではありません。このオプションが説明するのは実行中のプロセス内の一つの再起動経路であり、systemctl stop はその経路ではありません。
二つの名前を並べて読むと、設計が明確になります。一方は記述子を保持し、もう一方は鍵素材を保持し、どちらも特権を手放した後に起きることのために存在します。
二つのリソースとそれらが属するリセット
OpenVPN は、二つの通常の状況で自身の再起動を通知します。明示的な SIGUSR1 がそうし、死んだピアによって引き起こされる ping-restart も同じことをします。どちらもプロセスを生かしたまま接続の設定を再実行し、そこにこそこれらのオプションの居場所があります。
| Event | TUN/TAP device | Key and auth files | Addresses and routes | up/down hooks |
|---|---|---|---|---|
Soft reset, from SIGUSR1 or from a ping-restart the daemon sends itself | survives only with persist-tun | survive only with persist-key | survive with the device, otherwise rebuilt | run again only when restart hooks are enabled |
Configuration reload, SIGHUP | recreated | re-read from disk | rebuilt once the device returns | run again |
| Service stop | lost | re-read at the next start | removed | run at the next start |
これら二つのオプションが変えるのはソフトリセットの行だけであり、彼らが飛ばす作業は混雑した回線では高価な部分です。デバイスを開き直すと、それに付随するアドレスとルートが破棄され、それらを再構築するとリセット開始時に転送中だったパケットが落ちることがあります。停止は同じオブジェクトを保持するオプションなしで破壊します。
そもそもなぜこれらのオプションが存在するのか
強化された OpenVPN サーバーは通常 root として起動し、鍵とデバイスを開いてから、特権のないユーザーに降ります。その移行後、一部の操作は単に失われます。モード 0600 の鍵ファイルの読み取り、ネットワークインターフェースの作成、ルートの変更はすべて拒否される可能性があります。
persist オプションがなければ、ping-restart を引き起こすほど長く沈黙したピアが、まさにそれらの操作を強制します。設定に何も変わっていなくても再接続は失敗します。プロセスは理由もなく死んでいるように見え、ログにはネットワークエラーではなく権限エラーが表示されます。
それらがあれば、ソフトリセットは特権フェーズがすでに取得したものを再利用します。魔法はなく、プロセスは何も生き延びません。リソースの取得が単に先送りされるだけです。
最後ではなく最初のエラーを読む
リセットが失敗したら、最後ではなく最初のエラーを読んでください。保護された鍵、auth ファイル、インターフェースの ioctl、外部フックは四つの異なるリソースです。一つを保持しても、他へのアクセスについては何も言えません。ファイアウォールツールを呼び出すフックは、そのツールが要求する特権を依然として必要とします。
フックには独自のスイッチがあります。OpenVPN のマニュアル は persist オプションを up-restart と組み合わせており、再起動後に up スクリプトと down スクリプトを再実行するかどうかを決めます。したがって、起動したままのインターフェースは、リゾルバー統合が更新されたかどうかを何も教えてくれません。
# which restart path just happened?
journalctl -u openvpn-client@office --since '10 min ago' | grep -E 'SIGUSR1|ping-restart|Restart pause|NOTE:'
# did the interface survive, and do its routes still exist?
ip -brief link show tun0
ip route show dev tun0
この二つのコマンドは、二つの障害モードを数秒で切り分けます。存在するがルートが欠けているインターフェースは、フックかルートの問題です。 消えたインターフェースは、プロセスが実際に終了したことを意味します。
保持されたインターフェースは kill switch ではありません
要件が「通信がトンネルの外に出てはならない」である場合、保持されたデバイスはそれを提供しません。もう一方のアドレスファミリのルート、二番目のデフォルトルート、プロセスが完全に終了するケースは、すべてこのオプションの範囲外です。
二つの要件を別々に扱ってください。再接続をまたいでトンネルオブジェクトを保持することは、デーモンにとっての便利さです。トンネルがダウンしているときに外向き通信を遮断することは、独自のルールと独自のテストを持つファイアウォールポリシーです。両者を混同すると、防御的に見えてベストエフォートの再接続のように振る舞う設定になります。
診断する前にイベントに名前を付けてください。ソフトリセット、失敗した接続試行、サービスの停止は三つの振る舞いを持つ三つのイベントであり、最初のものだけがこれらのオプションの説明対象です。