最初の一秒で死ぬ VPN は、接続してから失敗する VPN とは別の生き物であり、両者を同じものとして扱うのがよくある誤りだ。ここにはハンドシェイクも、証明書の交換も、調べるべきルートもない。ジャーナルの一行が、無関係ないくつかの修理のうちどれが当てはまるかを決めており、それを見落とすと、一度も読まれなかった設定を編集して半日を失う。まずその行を読むこと。

読み取り専用のコマンド三つ、つまり最初の journalctl -u openvpn@server -b --no-pager、次の systemctl status openvpn@server、そして UDP のリスナーとその持ち主のための ss -lunp でそこへ行ける。

最初の行が分岐を選ぶ

ポートの衝突もバイナリの欠落も、どちらも一秒以内に起動を殺し、しかも残す最初の行が違う。アドレスが使用中というメッセージはポートを名指しし、実行ファイルの欠落はもう存在しないパスを名指しし、失敗した条件や設定ファイルの不在はそのファイルを名指しする。この三つは別々の修理へと導き、どれもクライアントの再インストールでは改善しない。ほかを実行する前に、最初の失敗をメモに写しておくこと。

元の行を隠す再試行ループに注意する。再起動ポリシーを持つユニットは最初の失敗を十数個の同一の失敗の下に埋めかねないので、ユニットで絞って先頭から読む journalctl -b が末尾より勝る。

ほかに誰が 1194 番ポートを握っているのか

原因は通常、誰かが意図的に設定した二台目のサーバーではない。別の端末でまだ生きている手動起動のクライアント、たまたま同じポートを選んだ二つ目のプロファイル、あるいは自前のトンネルが 1194 を保持しているベンダーのバンドルを想定しておく。ソケットの持ち主は ss -lunp に現れ、その PID を systemctl status に渡せばユニットが責任を負っているか分かる。シグナルではなく、そのユニット自身の制御経路で止めること。

ユニット管理下のプロセスへのシグナルは通常再起動を引き起こし、同じ失敗が数瞬後に新しい問題のように再び現れる。ユニットには systemctl stop を、ベンダーのインストールにはバンドル自身のサービスコマンドを、シグナルはそのシェルで自分が手で起動したものにだけ使う。

削除後に残るユニット

削除はバイナリを消すが、手書きのユニットファイルは、ふつう /etc/systemd/system の下にあり、それを生き延びる。すると Systemd はもう存在しないパスを指すユニットを再試行し、メッセージは昨日の削除ではなくその欠落ファイルについて語る。systemctl status はユニットのフラグメントパスを上部に示すので、何かを消す前に dpkg -S で確認すること。孤児が消えたら systemctl daemon-reload と systemctl reset-failed が状態を片付け、そうしなければ以降の状態確認がすべてその状態を引き継ぐ。

which openvpn が /usr/local の下の何かを返すとき、使われているバイナリは apt ではなくベンダーのインストーラ由来だ。その種のインストーラは通常、独自のリスナー、独自の起動エントリ、独自の設定ディレクトリを持ち込むので、見えるコマンドを消してもソケットはふさがったままになる。

ベンダーが文書化している方法でアンインストールし、ss -lunp でポートが空いたことを確認し、必要ならディストリビューションのクライアントを追加する。

再試行の前に状態を整える

systemctl reset-failed がカウンタを消し、そのうえで systemctl status はユニットの履歴ではなく現在の状態を報告するので、結論を出す前に失敗状態を片付けておく。一度起動して、機械全体の集約状態ではなくその実行自体のジャーナルを読むこと。トンネルが何も運んでいないのに active と報告するユニットは別の問題で、こちらのほうがずっとよくある。両者はバグ報告で混ざる、どちらも「VPN が動かない」という利用者の言葉で終わるからだ。

どの分岐を取ったか、つまりポートの衝突か、バイナリの欠落か、設定の欠落かを書き留める。次に起きたときはもっと早く見分けられる。

関連記事