Transport Layer Security(TLS - RFC2246 :: 日本語訳)はSSLの後継ですが、実際にはむしろSSLという言葉をTLSの意味で使う事が多いと思います。 SSL v2をデフォルトで無効にする実装は増えていますが、とりあえずはSSLとTLSは区別なく使うことにします。
また基本的に自己認証CA局とサーバ認証書を利用する前提で書いています。
ここに至る経緯
サーバアプリケーションの設定をしていると、たいていSSLの設定項目はオプションですが、stunnelのように基本機能に組み込まれている場合はパッケージがPEMファイルを生成してくれたり、ejabberdのように(ほぼ)標準機能としてSSLを利用するサーバアプリケーションは(関心とともに)増えている印象です。
ejabberdの場合は混乱もなさそうですが、パッケージの導入時に生成されたPEMファイルはサーバ名の変更などに追従できずに混乱を招く場面も考えられます。
OpenSSLを利用していても設定方法はサーバアプリケーション毎に違い、SSLはいろいろ自分で混乱するところなので、自分の理解している範囲をまとめておこうと思いました。
SSL関連の設定項目への疑問
OpenSSLはいろいろなプログラミング言語でバインディングライブラリが用意されていますが、大抵はプログラマがOpenSSLを理解している前提でC APIへのマッピングだけが記述されていて、使い方とか最低限必要な項目なんかは分からないものだという印象を持っています。
サーバ管理者になると、バインディングライブラリ設計者に加えて、さらにプログラマの実装を1段挟んで設定ファイルと格闘することになるわけです。
アプリケーションでのSSLの設定手順は各ガイドの作者によって微妙に違っていて、他のアプリケーションでの知識/経験との連携が難しいのかもしれません。
いろいろ調べているとサーバアプリケーションを設定する際の疑問で、「なんでサーバ側でcacert.pemファイルを設定しなきゃいけないんだ」、「この項目は必要なの?」という発言を目にする機会がありました。
Certificate Revocation List (CRL)とかの扱いはサイト毎のポリシーの問題ですが、「これ設定必要なの?」みたいな疑問を持ってしまうと、いろいろある設定項目に手を出してはまってしまうかもしれません。
SSL証明書を管理するベストな方法は?
サーバアプリケーションを使うためにマニュアルやガイドを確認して、意味もわからずに手順通りに文字列を打ち込んで生成されたファイルを言われるがままにサーバに配置したりするのが実情なのかもしれません。
であれば、なおさら何かソフトウェアを利用したところで、そのソフトウェアの手順に書かれていない事や、そのソフトウェアの対応していないアプリケーションを利用すると、とたんに混乱しそうです。
これを読めば完璧というものもなさそうですが、基本的なところを理解しておけば混乱を少なくする事はできそうな気がします。
TLS/SSLの基本的な処理フロー
RFC 2246( 日本語訳)によれば、次の図のように、通信を開始するまでにサーバ証明書(Server Certificate)の送信と、オプションであるクライアント証明書の送信が行なわれます。
ここでのポイントはクライアント証明書の送信は任意である点で、サーバは特定のクライアントとだけ通信を行ないたい場合にクライアント証明証を要求します。
後述するように、通信のためには、サーバは自身の証明書の出所を検証する必要はありませんから、サーバ側が持つcacertはクライアントから証明書が送信された場合にだけ、そのクライアント証明書を確認するために使用されます。
クライアントの送付してくる証明書によってサーバ側が持つべきcacertは変化しますから、もし不特定多数のクライアントとのクライアント認証をすると考えると、サーバ側は世の中にある中間CA局を含めたcacertを収集しなければいけなくなるという事です。
クライアント認証はID/Passwordの代りになるか
最終的には、用途や役割をよく考えて、ロールプレイなどによってより適切な利用方法を検討することになります。
基本的にクライアント証明書はファイルという電子化されている物証によって個人を特定する事ができますから、記憶に依存するID/Passwordによるログイン認証と、性質は違いますが、同じ役割を果します。
クライアント証明書は数年という単位で流通して、一時的なアクセス制限を加えるには不向きです。 CLR配布の問題は常にありますし、サーバ側で証明書を許可対象から外すのも手間であったり確実性に欠けます。
この点ではLDAPなどにより集中管理されたID/Passwordがより向いているでしょう。
しかしどちらが常に優位であるという事はありません。
もしアクセスが特定のネットワーク内部で、バッチ的なプログラムから行なわれる場合には、大抵のケースではクライアント証明書のみによるアクセス制限がメンテナンスと堅牢性のバランスから選ばれると思います。
その反面、人間によるインタラクティブなアクセスに対しては、ID/Passwordによる認証の方が、ユーザの教育という観点からも、適切な場面が多いと思います。
さらにユーザが不特定な場所(インターネット)からアクセスしてくる場合に、クライアント証明書の配布を加えて行なう事は現実的な対応です。
とはいえ認証(Authentication)と承認(Authorization)の問題を含めて、アプリケーションが提供する機能が不足していれば、その制限を考慮しなければいけません。
認証と承認の問題は別のトピックなので、元に戻して証明書ファイルの扱いについて、まとめていきます。
cacertとcertとkeyファイル
通信に使われる情報として、CLRなどの付加的なファイルを除いて、最低限必要な組み合せという点では (通信相手の証明書を発行した)CA局のcacert、 cert、 keyの3つの情報があります。
certとkeyファイルを生成するrequestファイルは作業が終ったら削除しましょう。
ポイントはクライアントやサーバが持つcacertの情報は、通信の相手方の証明書を発行した局の情報だという点です。
自分の理解をまとめると次のような図になりました。
ポイントはサーバは認証自体にはクライアントから送られてきたclient.cert.pemとそれを発行したcacert#1.pemを使いますが、実際には全ての通信を許可するわけではないので、承認(Authorization)には、そのclient.cert.pem自体を別途許可リストとして登録しておく必要があります。
stunnelでは図のcaert#1.pemとclient.cert.pemの情報を"-a"オプションに指定するディレクトリに入れて、c_rehash <directory>を実行することで、サーバに登録する事になります。
自分の理解をまとめると、だいたいこんな感じです。
CA局の信頼性について
世の中には自己認証によるCA局ファイルを配布しているグループがあります。
遊びとして興味はそそられますが、そのcacertを自分のブラウザの許可リストに入れておこうとは思いません。
あるいはopenca.orgがOpen CAアプリのデモで動かしているCA局が発行する鍵ファイルをそのまま使うのは間違った行為です。
遊びとして相応しい対応は自分でPKIを構築する事で、他人と(別の他人が作った)rootCAを共有することではありません。 rootCAの共有は自分の家の鍵を他人に渡すようなもので、そのリスクが受容できる場合には、なかなかおもしろい経験になるでしょう。
鍵ファイルが高いという人や、無料のCAを使おうという人もいるけれど…
自己認証による(プライベート)CA局の運営は 利害の一致する各個人や組織の中で行なわれるべきものです。 これは鍵ファイルを買いましょう、という話ではありません。 むしろ適切な場面では、プライベートCAの運営を行なってノウハウを蓄積するべきです。
しかしイントラネットのサーバに社内にきた外部の人間がPCを繋いでアクセスするのであれば、そのWebサーバには商用CA局が発行する鍵ファイルを使うべきです。
あるいは組織が肥大化してrootCAが2つ以上存在するのであれば、そういうガバナンスの存在しない場面では、商用CA局の発行する鍵ファイルや、プライベートCAのアウトソーシングを使うべきでしょう。
そうでない場合、社内で配布するPCに自社で運用するCA局のcacertを含めて配布するのは悪いアイデアではありません。
けれども、プライベートCAの認証する末端のデバイスや個人が自分と利害の対立するものでない事を確認してください。 これは、そのCA局の運営方法(むやみに証明書を発行しない、証明書を発行するPCは一つだけ、等)も含めて考えるという事です。
職権の分離に応じて中間CA局を設けて、必要な範囲にのみその中間CAの配布する鍵ファイルと、デバイスにcacertを配布するという使い方はより望ましいでしょう。
結局、この問題には銀の弾丸は無くて、状況をいろいろ考慮して柔軟に解決するべき問題だとしかいえないんですけどね。だから論争(というよりも口論)にもなるんでしょうけれど。
0 件のコメント:
コメントを投稿