ノートPCが復帰するとOpenVPNが死ぬのはなぜ?
スリープはOpenVPNセッションを殺したままtun0を残すことがある。トンネルを検証し、次にデバイスではなくsystemdのスリープフックからユニットを再起動する。
マシンをサスペンドしてから復帰させ、設定に触れる前に三つのことをこの順で確認してください。tun0 がまだ存在するか、内部アドレスへの経路がまだそれを選ぶか、サーバーがまだこのピアを一覧に載せているかです。経路がどこか別を指しているのにデバイスだけ生き残っているなら、それは残骸であってトンネルではありません。経路が正しいのに通信が死ぬなら、障害はトンネルの上にあり、クライアントの再起動では変わりません。再起動の自動化が意味を持つのは、手作業の検証で三つのうちどれなのかが分かってからです。
ip -br address show tun0
ip route get 10.20.0.10
journalctl -u openvpn-client@office -b --no-pager | tail -30
自動化する前に復帰を再現する
サスペンドはデバイスを取り除くよりも多くの場合で暗号化セッションを終わらせます。トンネルを生かしていた UDP の流れが止まり、サーバーはピアを落とすことがあり、クライアントは気づいて再接続するか、背後に何もないインターフェースを抱えたままになります。インターフェースの確認だけではほとんど証明になりません。なぜなら 古いデバイスは動作中のものとまったく同じに見える パケットがそこを通らざるを得なくなるまでは。経路の照会と実際のリクエストを一つトンネル越しに実行し、そのうえで復帰の瞬間の前後のログを読んでください。
クライアントが自力で戻ってくるなら、フックは信頼性ではなく手間を増やします。決して復旧しないなら、自動化こそが正直な対処です。
systemdのスリープフックが実際に置かれる場所
古い解説の多くは /etc/pm/sleep.d を指しますが、これは pm-utils が管理するディレクトリで、systemd ベースのサスペンドが参照することはありません。systemd は /usr/lib/systemd/system-sleep/ と /etc/systemd/system-sleep/ からフックを読み、第一引数にフェーズ、第二引数に操作を渡すので、フックが分岐する値は pre と post だけです。パッケージ側のファイルを編集するのではなく、ローカルの複製を /etc の下に置いてください。スクリプトは遷移の途中で root として動くため、素早く戻る必要があります。
#!/bin/sh
case "$1" in
post)
systemctl --no-block try-restart [email protected]
;;
esac
exit 0
try-restart はすでにアクティブなユニットにしか触れないので、意図的に落としたトンネルは復帰をまたいでも落ちたままです。--no-block はクライアントが交渉している間フックが待つのを防ぎ、ネットワークがまだ上がっていないときに効きます。二つのフラグを併せると、復帰の流れ全体を止める代わりに静かに失敗するフックになります。ユニットがすでに停止しているときは何も起こりません。それがまさにそこで望む結果です。
サービスを復旧させ、tun0には触れない
tun0 を手で落とすと、デーモンはもう所有していないインターフェースを監督し続け、次の状態変化で分かりにくいエラーが出ます。インターフェースではなくサービスかその接続プロファイルを対象にし、まず正確なユニット名を確認してください。ディストリビューションのパッケージ、OpenVPN 3、NetworkManager はそれぞれ違う名前を選ぶからです。 NetworkManagerのプロファイルは、その接続を循環させると戻ってくるしたがってそこで対象になるのは systemd ユニットではありません。仕組みが何であれ、手作業で確認したのと同じ操作であるべきです。
再起動はクライアントが接続時に押し込んだ経路を入れ直します。ほとんどの復帰ではそれが望ましいです。自分で経路を足したマシンでは望ましくないので、復旧が戻したと決めつけずにそれらを再確認し、次の復帰が見つけられる場所に書き留めてください。
自分で制御できないタイミングに対処する
無線の関連付けと DHCP はフックが走った後に終わることが多く、サーバーへの経路がまだないうちに再起動が失敗することがあります。そのアドレスを少し待ち、一度だけ再試行し、結果を記録してください。
名前解決は別の競争です。デスクトップのネットワークスタックはトンネルが上がった後に DNS を復元することがあります。動作する経路から推測するのではなく、resolvectl query internal.example で検索を単独で検証してください。正しく経路を選びながら何も解決しないトンネルは DNS の問題であり、フックの問題ではありません。
フックの判断を見える形にするため、フェーズ、ユニット名、結果をジャーナルに書いてください。どの復帰テストを実行したかをマシンの記録に残せば、機能する復旧と偶然の復旧を区別できます。サービスを戻す最も負担の少ない操作を選び、自力で復旧するクライアントにはそうさせてください。完全な再起動は進行中のセッションを落とし、一日に何度も復帰するノートPCでは実際のコストになります。