VPNクライアントは「証明書を検証できませんでした」と告げ、ダイアログはそこで止まります。ファイルはあり、サーバーも動いており、同じプロファイルは先月別のノートPCで動いていました。その一行の警告の下で、クライアントはピア証明書を、設定した認証局が署名経路を保証しているか、その経路が認証局に届くか、ピア名が要求した名前か、証明書が今この用途に使えるかという四つの関門に通しています。閉じた関門を見つければ修理はたいてい一ファイルで済みますが、その手順を飛ばせば午後じゅうバンドルを再インポートすることになります。

プロファイルを編集する前にダイアログを読む

証明書のエラー文言を書いているのは、インストールしたVPN製品ではなくその下のライブラリなので、正確な文字列が最初の証拠になります。「ローカル発行者の証明書を取得できません」は経路か信頼の基点を指します。「証明書の有効期限が切れているか、まだ有効ではありません」は時刻を指します。「サポートされていない証明書の用途」は拡張鍵用途を指します。名前の不一致は、どの名前を求めていたかを教えてくれます。四つのどれも、クライアントの再インストールでは直りません。

何かを変える前にログの水準を上げます。OpenVPN は --verb 4 を付けて実行すると、ハンドシェイク周辺の検証失敗を報告し、strongSwan は身元とチェーンの判断を charon ログに書きます。次に、人はディスク上のファイルを試すのにプロファイルは古いコピーを内部に埋め込んでいることがよくあるため、調べている証明書がどれかを確認します。プロファイルが PEM ブロックを埋め込んでいるときは、埋め込まれた証明書が試験対象です。

認証局は身元に署名するのであって、権限に署名するのではない

認証局は名前と署名鍵を持ちます。自分のポリシーに従って公開鍵をその名前に結びつける証明書を、有効期間と使用制約を添えて発行します。クライアントが発行者を認識するのに必要なのは認証局の証明書だけで、署名鍵は決して必要なく、その鍵をクライアントに配れば展開が信頼するどの身元でも作れてしまいます。

認証局を信頼すると、それが署名したすべての証明書が候補になり、正しいピアとは限りません。同じ社内 CA の Web サーバー証明書も候補です。だから名前と用途の関門があり、侵害された CA 鍵が単一のサーバーより重いのは、その鍵が認証局の発行したすべての身元に届くからです。端末ごとにクライアント証明書を配れば、ノートPCの紛失は展開全体の鍵交換ではなく、一件の失効で済みます。

クライアントが構築しようとしている経路を再現する

経路はピア証明書から、ゼロ個以上の中間証明書を通り、信頼ストアのルートに至ります。中間証明書の欠落は最も多いチェーンの故障で、クライアント側から見ると 信頼されていないルート とまったく同じに見えます。まずリーフを読み、次に配布するつもりの素材から OpenSSL に経路を構築させます。

openssl x509 -in server.crt -noout -subject -issuer -dates
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt
openssl verify -show_chain -CAfile root.crt -untrusted intermediate.crt server.crt

終了ステータスがゼロならそのファイル群から経路が構築できており、失敗した場合は到達できなかった証明書の名前が出ます。openssl verify が成功するのにクライアントが拒否するなら、違いはサーバーが実際に送る内容か、プロファイルが読み込む信頼ファイルにあります。OpenVPN では中間証明書をサーバー証明書ファイルに同梱することも --extra-certs で別に渡すこともでき、同じサブジェクト名の下に二つのルートを持つバンドルはクライアントの一つを誤った枝へ送ります。

名前と用途は別々の関門

チェーンの構築は、名前が自分のものかを問いません。OpenVPN が確認するのはプロファイルが --verify-x509-name を設定したときだけで、コモンネームだけを照合する古い習慣は、身元が subjectAltName にある証明書で破綻します。IKEv2 の展開では、設定した身元を SAN の項目や識別名と照合しますが、どちらを使うかはクライアント次第で、ワイルドカードや %any の値はあると思っていた比較を静かに無効にします。

次に時刻と用途です。時計が数時間進んでいるノートPCは、まだ有効でない証明書を拒否し、期限切れの中間証明書はリーフが有効でも経路を失敗させます。用途の失敗は、拡張鍵用途に serverAuth がない証明書か、ハンドシェイク署名を許さない keyUsage を持つ証明書から来て、OpenSSL はこれをサポートされていない証明書の用途として報告します。再発行は正しいテンプレートから行い、そのメッセージのどこにも検証を切る理由はありません。

失効は誰かが設定したときにだけ動く

CRL や OCSP 応答は自動では参照されません。OpenVPN サーバーでは、--crl-verify がリストを指しているときだけ、クライアント証明書がリストと照合されます。サーバー証明書のクライアント側の確認は実装次第で、多くの場合ありません。strongSwan はピアの CRL を見る前に、失効プラグインとポリシーを必要とします。

これで、いずれ受け取るチケットの意味が分かります。失効したクライアント証明書がまだ接続でき、全員が失効は壊れていると結論しますが、実際には何も確認していなかったのです。CRL を発行して更新するか、クライアント証明書を十分に短命にして古い失効の意味を短く保ち、インシデントで必要になる前に実験用証明書で失効の経路を練習しておきます。

検証を切らずに済ませる修理の順序

ファイルに触る前に、表の各行がそれぞれ別の対象へ導くため、症状で並べ替えます。

Client saysMost likely gateFirst check
unable to get local issuer certificatetrust anchor or missing intermediateyour own openssl verify against the files the profile loads
expired or not yet validvalidity windowleaf and intermediate dates against the device clock
unsupported certificate purposeextended key usageserverAuth present, keyUsage allows the handshake
name mismatchpeer identitysubjectAltName entries versus the profile name

一巡で、プロファイルが読み込むファイルを確認し、経路を自分で構築し、サーバーが中間証明書を送っているかを確かめ、時計を比べ、SAN を読み、EKU を読み、それから再接続して同じログ行が消えるのを見ます。端末に CA をまったく与えられないなら、OpenVPN 2.6 が --peer-fingerprint を受け付けて確認を外すのではなく信頼を一つの鍵に狭めるため、ピン留めが正直な代替です。こうした各フィールドの意味については RFC 5280 が参照先です。

関連記事