ConnMan は半日ほど動いたあとに接続を拒否し、ジャーナルの行は証明書の検証に触れています。その一行が、決して壊れていなかった CA バンドルへ人を向かわせます。二つの別の障害が、ほとんど同じ形の失敗を生みます。セッション Cookie が失効したのか、サーバー証明書が実際に変わったのかです。どちらかは一分ほどで切り分けられ、フィンガープリントが関わるのは片方だけです。

二つの障害、一つの紛らわしいログ行

両者は二つの観察で分かれ、どちらも二度読みする必要はありません。一つ目は失敗がいつ始まったかです。失効した Cookie は数時間あるいは数日動いたあとに現れ、差し替えられた証明書はゲートウェイの変更直後に現れます。

SignalExpired cookieChanged certificate
When it startedafter hours or days of workingright after a gateway change
Fingerprint from a fresh authenticateunchangeddifferent value
Usual log tailHTTP CONNECT 401 / unauthorizedsigner not found / verify failed
Repairreplace the cookie, restartre-pin deliberately, then restart

一分の確認とは、下の authenticate の実行です。その FINGERPRINT をファイル内の OpenConnect.ServerCert と比べてください。フィンガープリントが同一で COOKIE だけが違えば、Cookie だけを差し替えます。フィンガープリントが違えばサーバー証明書が実際に変わったので、意図してピン留めし直し、誰が承認したかを記録します。

入力するのではなく生成する

ConnMan には NetworkManager と違い、OpenConnect プロファイルを取り込む手順がありません。値をあらかじめ用意しておく必要があるプロビジョニングファイルを読み込み、それを用意する正式な方法が OpenConnect の authenticate モードです。

sudo openconnect --csd-wrapper=/home/user/.cisco/csd-wrapper.sh \
  --authenticate --user myuser vpn.example.com

出力は四つの値を表示します。POST、COOKIE、HOST、FINGERPRINT です。sha256: を前に付けたフィンガープリントがサーバーのピン留めです。Cookie はゲートウェイが寿命を決めるセッションの産物です。両者は別種の秘密として扱ってください。失効する周期が異なり、変わるのは片方だけだからです。

ファイルは両方を抱えており、老い方が違う

プロビジョニングファイルは /var/lib/connman-vpn/ の下にあり、トレイのアプレットではなく VPN デーモンが接続ごとに読みます。接続名はグローバルセクションに、プロトコルの詳細はプロバイダーセクションに置いてください。

[global]
Name = Company VPN

[provider_openconnect]
Type = OpenConnect
Name = Company Cisco VPN
Host = vpn.example.com
Domain = corp.example
OpenConnect.ServerCert = sha256:...
OpenConnect.Cookie = ...

ポータルが実際に配信しているホスト名を使ってください。素の IP アドレスは証明書の検査を通っても失敗します。機器は仮想ホストで振り分けており、名前を期待しているからです。

systemctl status connman-vpn --no-pager   # is the daemon even installed and running
sudo systemctl restart connman-vpn       # after the file edit
journalctl -u connman-vpn --since '1 hour ago'  # after the connection attempt

ジャーナルが実際に示すもの

トレイのツールチップは、どちらの障害かを教えてくれません。最初の目を引く行ではなく並びを読めば、ジャーナルが教えてくれます。古い Cookie では通常、TLS の交渉が完了したあとに HTTP 層が拒否したことが示され、だからこそ証明書に関する言葉が認証の失敗の隣に並びます。

新しい authenticate の実行をファイル内の値と比べてください。フィンガープリントが一致し Cookie だけが違えば、信頼の設定に触れずに答えが出ます。

失効した項目を更新する

authenticate コマンドを繰り返し、OpenConnect.Cookie を差し替えてデーモンを再起動します。新しい出力が別の値を示さない限りフィンガープリントはそのままにします。その場合はサーバー証明書が実際に差し替えられており、ピン留めし直しは誰かが記録すべき判断であって、エラーメッセージからの貼り付けではありません。

更新を自動化するのは妥当です。小さなスクリプトが標準入力からパスワードを読み、authenticate モードを実行し、Cookie の行だけを書き換えます。認証情報はスクリプトの外に置き、実行するアカウントだけが読めるようにし、書き換えは不可分にして、失敗した実行が中途半端なファイルを残さないようにします。

更新が数時間ごとに必要なら、その間隔を書き留めてください。それはゲートウェイのセッション方針の性質であり、更新を自動化するか、より長いセッションを求めるかを決めます。

関連記事