同じイメージから作った Ubuntu が二台、VPN プロファイルは一つ、ログイン時の結果は正反対です。一方ではデスクトップが現れる前にトンネルが上がり、もう一方では決して上がりません。ここで変数になっているのはプロファイルではありません。三つの構成要素のうち、どれに起動を命じたかが違いであり、その三つは同じスイッチを共有していません。

並べて比べるほうが、当て推量より速いです。どれも特徴のある壊れ方をしますし、だからこそ比べる価値があります。

引き金の異なる三つの起動役

パッケージ版の openvpn サービスは最も古い経路です。その init スクリプトは /etc/default/openvpn から自動起動リストを読みます。そのリストがコメントアウトされているか空のままだと、スクリプトはあなたが追加した一つではなく、そのディレクトリで見つけたすべての設定を起動します。一つのトンネル用に足したファイルが、黙って複数を立ち上げることがあるのです。

StarterWhat triggers itTypical failure
Init script and templated unitsBoot, plus anything in the autostart listStarts every config, not the one you meant
NetworkManager secondaryActivation of the base Wi-Fi or Ethernet profileNothing happens until that base link comes up
Hand-written unit or wrapperWhatever its WantedBy and ExecStart sayRuns a different binary or environment than your shell

設定を誤るのは二行目の方式です。NetworkManager は取り込んだプロファイルを保持し、それを起動しますが、あくまで別の接続のセカンダリとしてであり、引き金は VPN ではなくネットワーク側のリンクに属します。

設定の手間と適用範囲を比べる

init スクリプトの経路は一行の設定で済み、マシン上のすべての設定を対象にします。ルーターには向いていますが、複数のネットワークにつなぐノート PC には不向きです。NetworkManager の経路は UUID の検索が要り、トンネルを一つの基本接続に結び付けます。職場の SSID では上がり、ホテルのネットワークでは下がったままになります。

手書きの unit は最も手間がかかり、他のサービスとの順序付けも含めて最も多くの制御を得られます。決め手は適用範囲です。マシンにネットワークが一つ、トンネルが一つなら、パッケージ版のサービスは素直で予測できます。トンネルを特定の Wi-Fi に追従させたいなら、追加のスクリプトなしでその条件を表せるのは三つのうちセカンダリだけです。

持ち主を一つに決め、残りを外す

二人の持ち主が起動するプロファイルは、起動のたびに変わるタイミングを生みます。どちらか一方だけを使うより悪い結果です。持ち主を決めたら、競合する経路は事故ではなく意図的に無効化してください。

# who is configured to start something?
grep -v '^#' /etc/default/openvpn
systemctl list-units 'openvpn*'
nmcli -g connection.secondaries connection show 'Work Wi-Fi'

# NetworkManager: attach the tunnel to the base link by UUID
TUNNEL=$(nmcli -g UUID connection show 'Corp Tunnel')
nmcli connection modify 'Work Wi-Fi' +connection.secondaries "$TUNNEL"

引退させるのがパッケージ版の経路なら、順序を守ってください。AUTOSTART を none にし、systemctl daemon-reload を実行して生成済みの unit に新しいリストを読ませ、そのうえで不要になったテンプレートのインスタンスを無効にします。再読み込みを飛ばすと古い unit が有効なまま残り、変更が効かなかったように見えます。

止まらない停止は別の問題で、答えは限られています。TimeoutStopSec は、systemd が SIGKILL を送るまで待つ時間の上限を決めます。設定を置くべきは drop-in です。パッケージ版の unit を直接編集すると、次の更新で変更が失われます。

実際に何が起動したかを確かめる

再起動して、設定ファイルを信じるのではなく証拠を読みます。トンネルを持つ unit は有効な状態と起動時刻に合うタイムスタンプを示し、VPN インターフェースはログイン前に存在しているはずです。

systemctl is-enabled openvpn-client@office
systemctl status openvpn-client@office --no-pager
nmcli -f GENERAL.STATE,connection.secondaries connection show 'Work Wi-Fi'
ip -brief link show tun0

もう一つ確かめるべきことがあります。unit の ExecStart が、あなたの想定どおりのバイナリを指しているかです。ローカルでビルドしたクライアントや snap パッケージは、明示的なパスや snap run のラッパーを必要とすることがよくあります。systemd はシェルの検索順序を引き継がないからです。command -v openvpn と unit ファイルを見比べれば、数秒で決着します。

選んだ持ち主をプロファイル名の横に、マシンのメモとして書き残してください。次にトンネルの不在を調べる人は、同じ比較を繰り返すのではなく、その一行から始められます。

関連記事