強制終了された openconnect:ルートと DNS が今もトンネルを指している
死んだ openconnect プロセスはルートとリゾルバのエントリを残すことがあります。シャットダウンの経路をたどり、ビルドが文書化しているシグナルを送り、後片付けをしてください。
トンネルは落ちているのに、マシンはまだ上がっているかのように振る舞います。名前解決はタイムアウトまでぶら下がり、ルートはもう存在しないインターフェースを指しています。これは、切断用ヘルパーを実行せずに死んだ openconnect プロセスの痕跡です。それが作ったネットワーク状態はまだ残っており、システム上の他の何もそれを取り除く方法を知りません。
状態が作られた順にマシンをたどります。プロセス、リンク、ルート、リゾルバの順です。各手順で、クライアントが本当に消えたのか、単に端末から切り離されただけなのかが分かり、その違いが何かを修復すべきかどうかを決めます。
設定ではなくプロセスから始める
ルートに触れる前に、ターミナルを開いて何がまだ動いているかを確認します。pgrep -a openconnectは各インスタンスを引数付きで一覧表示し、pid ファイルと渡されたスクリプトを示します。予想していなかったプロセスは、どのログよりも速く幽霊トンネルを説明してくれます。
何も動いていなければ、リンクを見ます。ip link show tun0はインターフェースが生き残ったかを示し、ip route show dev tun0はまだ結び付いているルートを一覧表示します。次にリゾルバを次で確認します:resolvectl status。変更する前に三つの出力をすべて記録してください。その記録が、後で古いエントリと新しいエントリを見分ける手段になります。
消えたインターフェースは通常、そのルートも一緒に持っていきます。リンクより長く残るルートは、通常、プロセスがまだ生きているか、別のクライアントがデバイスを所有していることを意味します。
変更を元に戻すのはヘルパースクリプトです
openconnect はインターフェース、ルート、リゾルバのエントリを自分では削除しません。外部のヘルパーを呼び出します:/etc/vpnc/vpnc-scriptは upstream ビルドで、そして/usr/share/vpnc-scripts/vpnc-scriptDebian と Ubuntu のパッケージでは、次のオプションで選ばれます:-s。トンネルを立ち上げるのと同じスクリプトが、それを解体します。
プロセスがそのヘルパーを呼ばずに終了すると、状態は残ります。OpenConnect のマニュアルは、スクリプトなしではルーティングと名前サービスが正しく動作しないと明言し、終了時にインターフェースの状態を解体するコンポーネントとしてヘルパーを説明しています。だからこそ、クライアントを次のオプションで起動するときに経路が重要になります:-s。
どのシグナルがその経路に届くかはバージョン間で変わりました。7.06 のマニュアルは SIGTERM をスクリプトを飛ばす即時終了として扱います。現在のビルドは INT と TERM をクリーンな停止として文書化しており、セッションはログオフされ、ヘルパーが実行されます。どちらかの挙動を想定するのではなく、実際に手元にあるバイナリの SIGNALS の節を読んでください。
man openconnect | sed -n '/^SIGNALS/,/^LIMITATIONS/p'
ビルドが文書化しているシグナルを送る
シグナルが分かったら、パターンではなく pid でプロセスを停止します。
pgrep -a openconnect
sudo kill -INT "$(cat /var/run/openconnect.pid)"
その後、終了ステータスを信じるのではなく、最初の節の三つの確認を繰り返します。ip link show tun0は失敗するはずで、ip route show dev tun0は何も出力せず、resolvectl statusは VPN リンクを一覧表示しなくなるはずです。
SIGHUP は停止ボタンではなく、切断し、スクリプトを実行し、セッションを次のオプションで再開可能なままにします:--cookie。SIGUSR2 は即時の再接続を強制します。SIGKILL は後片付けを完全に飛ばします。それがまさにこの記事が扱っている状態です。
resolv.conf を置き換えずにリゾルバを修復する
ほとんどの Ubuntu システムでは、/etc/resolv.confは systemd-resolved へのシンボリックリンクであり、編集すべきファイルではありません。置き換えると VPN だけでなくすべてのネットワークの名前解決が壊れます。代わりにトンネルの登録を外します。
resolvectl revert tun0
resolvectl query example.com
システムが systemd-resolved ではなく resolvconf を使っている場合、インターフェースごとの記録はリンクを外すよう指示されるまで残り、resolvconf -d tun0が同等の操作です。コマンドを選ぶ前に、どのリゾルバが使われているかを確認してください。
死んだリンクの向こうのサーバーを依然として指す名前解決はタイムアウトまでぶら下がり、その遅延は残ったルートではなく壊れた DNS サーバーのように見えます。
次の切断を退屈にする
起動時と停止時で pid ファイルのパスを同じに保つには、毎回--pid-fileを渡すか、openconnect をユニットの下で実行しそのKillSignalが、お使いのバージョンが文書化しているシグナルと一致するようにします。先にフォアグラウンドで試すと、ヘルパーが出力する停止メッセージが分かります。
接続し、切断し、三つの確認を一度実行します。クリーンな終了なら VPN リンクも VPN ルートも VPN リゾルバのエントリも残りません。三つのうち一つでも残れば、どのコンポーネントが後片付けに失敗したかが分かります。次の調査は、ぶら下がった名前解決ではなく、その答えから始まります。