第12回 SSLによる安全なWebサイト作り

アクセス制限をもってしても、盗聴や改ざんには対応できない。通信経路をセキュアにしなければならない。今回は、SSLを用いてより信頼性の高いWebサイトを構築する方法を紹介する。

 IP認証、ユーザー認証、データベース認証と、Webコンテンツの閲覧を制限する方法を順に紹介してきた。しかし、盗聴や改ざんには対応できない。従って、悪意を持った第三者が、個人情報や機密情報を盗聴するかもしれない。ちょっと探せば、ネットワークの通信を盗聴するためのツールが無料で公開されているのが現実だからだ。

 盗聴や改ざんから身を守るには、通信信号を暗号化するのが最も簡単かつ確実な方法である。Web、すなわちHTTPの通信の暗号化には、SSL(Secure Socket Layer)を用いるのが一般的だ。なお、ApacheへのSSLの組み込み方法については連載第4回の「ApacheのSSL対応化と環境設定」を参照していただきたい。

SSLの仕組み

 SSLの仕組みは、本サイトでいくつか紹介されている。詳しくはそれらを参照していただくとして、ここでは簡単な説明にとどめる。

公開鍵、秘密鍵、共通鍵

 SSLによる暗号化には、公開鍵(Public Key)と秘密鍵(Private Key)、それに共通鍵が欠かせない。共通鍵は、いわゆる「扉の鍵」をイメージすればよい。つまり、暗号化と復号化に共通の鍵を使うのである。

 ところが、公開鍵と秘密鍵には、このイメージが通用しない。なぜなら、暗号化用の鍵と復号化用の鍵が異なるのである。公開鍵で暗号化されたものは秘密鍵でしか復号できず、秘密鍵で暗号化されたものは公開鍵でしか復号できない。これが公開鍵と秘密鍵のポイントである。

 公開鍵と秘密鍵はセットで作成されていて、その組み合わせでないと暗号化/復号化できない。また、公開鍵がその名のとおりだれでも入手できるのに対し、秘密鍵は自分だけが持っておく秘密の鍵となる。

 以上をまとめると、

となる。最初は戸惑うかもしれないが、これを押さえることが現代の暗号化技術を理解する第一歩となる。

秘密鍵/公開鍵の弱点

 秘密鍵と公開鍵の仕組みを使えば、暗号化は完ぺきであるように思える。しかし、ぱっと思い付くだけでも、この方式には2つの弱点がある。

 1つは、個人用の秘密鍵を一般ユーザーに作成させることの難しさだ。例えば、個人情報を送受信する商用サイトの場合、サーバから送信する情報には問題ない。サーバ側は、唯一の秘密鍵で暗号化し、信頼できる相手であることを証明する手段があるからだ。

 しかし、サーバに情報を送信する個人の側はそうもいかない。公開鍵で暗号化することはできるが、それはだれにでもできることである。通信の途中で、悪意のある第三者が割り込んで公開鍵で暗号化した情報をサーバに送信する可能性もある。こうなると、サーバは自分の通信相手を特定できないことになる。公開鍵と秘密鍵を使った暗号化は、通信する双方が秘密鍵を持っている必要性がある。個人にも秘密鍵を作成してもらえばいいのだが、それはだれにでもできることではない。

 もう1つは、暗号化と復号化に要する負荷の問題である。公開鍵と秘密鍵を使った暗号化は、思いのほかコンピュータに負荷が掛かる。大多数のアクセスを受けるサイトともなれば相当な負担となる。こうした負荷を軽減するために、「SSLアクセラレータ」と呼ばれる専用のハードウェアが発売されているくらいである。

 こうした理由から、暗号化には共通鍵方式を用いるのが望ましいのだが、ここに1つの問題が発生する。それは、どうやってサーバ側とクライアント(Webブラウザ)側で共通の鍵を用意するのかである。インターネットの世界では、特定の個人(Webブラウザ)だけがサーバにアクセスするとは限らない。従って、両者があらかじめ共通の鍵を保持することなど、現実的に不可能なのだ。そこで、SSLでは公開鍵と秘密鍵を使って共通鍵を相手に渡す、ハイブリッド方式を用いている。

共通鍵で通信できるまでの仕組み

 SSLが、公開鍵と秘密鍵を使った通信から共通鍵を使った通信に切り替えるまでの流れは、おおよそ次のとおりである。より詳細な仕組みについては、「身近なPKI〜SSLを理解する」が役立つだろう。

  1. WebブラウザからSSLによる通信をサーバに要求
  2. 署名付きの証明書とサーバの公開鍵を送付
  3. 共通鍵をランダムに生成
  4. 生成した共通鍵をサーバの公開鍵で暗号化して送付
  5. 共通鍵での通信を開始

 この手順からも分かるように、公開鍵と秘密鍵はWebブラウザとサーバ間で共通鍵を共有するまでの間だけ使われる。無事に共通鍵を使った通信ができる状態になると、肝心の通信内容を送受信し始める。

本当に信頼できる相手なのか?

 ところで、疑い始めればキリがないのが現代の世の中である。通信している相手は、本当にデータを送信していい相手なのだろうか? 受信しているデータは本物だろうか?

 通信相手が信頼できるかどうかを証明してくれるのが「証明書」である。そして、この証明書を発行してくれるのが「認証機関」(CA)である。認証機関は、サーバ所有者からの申請を受けて、認証機関の秘密鍵で暗号化された証明書を発行する。認証機関の秘密鍵で暗号化することで、証明書の改ざんや偽証明書の作成を防ぐのである。

 サーバは、先ほどの手順2でこの証明書とサーバの公開鍵をWebブラウザに送付する。Webブラウザは、あらかじめ組み込まれている認証機関の公開鍵を使って証明書を復号化し、このサーバが信頼できる相手かどうかを判断する。もし、組み込まれていない認証機関であったり、証明書を確認できなかったりした場合には、Webブラウザが警告を発する仕組みである。

 この辺りの話は、「PKIの基礎を理解しよう!」を一通り見ていただくのがいいだろう。証明書と認証機関の仕組みや概念は非常に重要なものだが、ここではサーバに証明書を組み込む必要があることを理解しておけばよい。また、証明書は認証機関によって発行されることも知っておいていただきたい。

独自認証機関の構築

 先の説明からも分かるように、広く一般に公開するサーバであれば、Webブラウザに証明書が組み込まれている信頼性の高い認証機関を利用する方がいいだろう。しかし、イントラネット内の暗号化など、対象とする範囲が限られているなら証明書の発行費用などを節約したくなる。そうした場合は、証明書や認証機関を独自に作成することもできる。

 独自に認証機関を構築して証明書を作成した場合、Webブラウザに認証機関の登録を行う必要がある。この辺りの説明も「PKIの基礎を理解しよう!」に詳しいが、ここでは認証機関の構築方法などを説明しておこう。

 認証機関は、OpenSSLの機能を利用して構築する。以下では、OpenSSLをデフォルトのディレクトリ(/usr/local/ssl)にインストールしているものとして話を進める。

 OpenSSLをインストールしたディレクトリにあるmiscディレクトリには、CA.shというシェルスクリプトが用意されている。このスクリプトはいくつかのオプションパラメータを持ち、-newcaオプションで認証機関を構築できる。具体的には、認証機関のファイルを格納するディレクトリ(デフォルトは「demoCA」)を作成し、証明書ファイルと秘密鍵ファイルを作成する。

 ファイルを作成するディレクトリやそのほかのオプションを変更したい場合は、CA.shを直接編集する。特に問題なければ、そのまま利用しても構わないだろう。ただ、miscディレクトリの中に作成するのは好ましくないので、CA.shを/usr/local/sslの下にコピーして実行する。また、認証機関の作成時にOpenSSLをインストールしたディレクトリの「openssl.cnf」が参照される。こちらも変更の必要は特にないと思うが、一通りチェックしておこう。

$ cp /usr/local/ssl/misc/CA.sh /usr/local/ssl/
$ /usr/local/ssl/CA.sh -newca

 上記のように実行すると、対話形式で処理が行われる。

CA certificate filename (or enter to create) 
Making CA certificate ...
Using configuration from /usr/local/ssl/openssl.cnf
Generating a 1024 bit RSA private key
..........................++++++
...............................++++++
writing new private key to './demoCA/private/./cakey.pem'
Enter PEM pass phrase: 
Verifying password - Enter PEM pass phrase: 
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Namer or a DN.
There are quite a few fields bur you can leave some blank
For some fields there will be a default value,
If you enter '.' the field will be left blank.
-----
Country Name (2 letter code)[AU]: 
State or Province Name (full name)[Some-State]: 
Locality Name (eg, city)[]: 
Organization Name(eg, company)[Internet Widgits Pty Ltd]: 
Organization Unit Name (eg, section)[]: 
Common Name (eg, your name or your server's hostname)[]: 
Email Address []: 
上位CAの証明書を持っている場合はファイル名を入力する。持っていない場合(新規に作成する場合は、そのまま[Enter]キーを押す)
作成する認証機関用の秘密鍵のパスフレーズ(パスワードのようなもの)を入力する
で入力したパスフレーズを再度入力する
国別のコード(日本の場合は「JP」)
州または都道府県名称
市区郡町村名
組織名称(会社名など)
組織内名称(部門名など)
管理者またはサーバの名称
管理者の電子メールアドレス

 以上のように、すべての質問に回答すると認証機関の作成が終了する。特にディレクトリ名などを修正していなければ、/usr/local/ssl/demoCAにファイルが作成されるはずだ。cacert.pemは認証機関の証明書、privateディレクトリ内のcakey.pemは認証機関の秘密鍵のファイルとなる。

SSL導入の下準備

 独自に認証機関を構築する場合も、外部の認証機関を利用する場合も、ここから先の作業は共通である。すなわち、

を行う。

鍵ファイルの作成

 鍵ファイルの作成には、やはりOpenSSLを利用する。

$ /usr/local/ssl/bin/openssl genrsa -rand file_name -des3 -out /usr/local/ssl/serverkey.pem 1024

 上記で指定しているオプションを順番に見ていこう。

-outオプション
サーバの秘密鍵ファイル名の指定

-des3オプション
暗号化の方式。このほかに「-des」と「-idea」が指定できる。des3は最も強力で、信頼できる暗号方式だ

-randオプション
鍵の生成に用いるランダムなデータとして利用するファイル名。何でも構わないので、適当なテキストファイルを指定する。例えば、何かのログファイルや設定ファイルなど

1024
生成する鍵のbit数。デフォルトは512bitだが、ここでは1024bitにしている。長ければ長いほど鍵を破られる可能性は低くなるが、パフォーマンスは劣化する。512bitか1024bit程度が適当であろう

 コマンドを実行すると、認証機関構築のときと同様にパスフレーズの入力を求められる。これは、鍵を参照するときの認証にも利用されるため、鍵を組み込んだApacheを起動するたびにパスフレーズが必要となる。つまり、Apacheを自動起動するにも毎度パスフレーズの入力を求められるということだ。これでは不便というのであれば、鍵の生成後にパスフレーズを解除することもできる。ただし、パスフレーズによるセキュリティがなくなるので、鍵の内容を盗まれやすくなることに注意したい。

 パスフレーズを解除する方法は簡単だ。パスフレーズを入力して鍵の内容を参照し、それをファイルに直接保存するだけだ。具体的には、OpenSSLのコマンドを使って次のようにして行う。

$ /usr/local/ssl/openssl rsa -in /usr/local/ssl/serverkey.pem -out /usr/local/ssl/serverkey.pem

 これによって、-inで指定した鍵ファイルを読み込み、-outで指定したファイルに書き込む。上記の例では入出力共に同じファイルを指定しているから、最初に作成した鍵ファイルが上書きされる。上書きしたくないなら、別のファイル名を指定すればよい。

認証機関への申請書(CSR)の作成

 サーバの鍵ファイルが作成できたら、その鍵を基に認証機関への申請書ファイルを作成する。認証機関は、この申請書ファイルに基づいて署名付きの証明書を発行してくれる。もちろん、実際にはファイルのみでの審査ということはなく、必要書類の提出や契約も併せて行われる。

 ファイルベースでの申請書の作成は、同じくOpenSSLを使って行う。申請書ファイルの作成は、独自に作成した認証機関を使う場合でも必要である。

$ /usr/local/ssl/bin/openssl req -new -days 365 -key /usr/local/ssl/serverkey.pem -out /usr/local/ssl/csr.pem

コラム CA.shによる鍵ファイル/申請書の作成
 ちなみに、サーバの鍵ファイルを作成する作業と認証機関への申請書の作成作業は、前述のCA.shでも実行できる。その場合は、CA.sh -newreqとすればいいのだが、鍵ファイルの長さなど詳細な指定はできない。指定したい場合はシェルスクリプトを修正することになる。

  その手間を考えると、個別にopensslコマンドを実行するのと大差ないだろう。

 コマンドを実行すると、国別コードや電子メールアドレスなど、認証機関を作成するときと同様の入力を求められる。それらに回答していくと、-outオプションで指定したファイルに認証機関への申請書ファイルが作成される。このとき、-keyオプションには作成済みの鍵ファイルの名称を、-daysオプションには発行してもらう証明書の有効期限を指定する。

証明書の作成

 申請書を作成したら、それを認証機関に送付して署名してもらう。実際に契約するのでなければ、独自に認証機関を構築するか、無料の試行サービスを利用するといいだろう。日本ベリサインでは、試行サービスを提供している。詳しくは、http://www.verisign.co.jp/welcome/try_verisign.htmlを参照していただきたい。

 今回の例では、先ほど作成した独自の認証機関を使って証明書を作成することにする。

$ /usr/local/ssl/bin/openssl ca -in /usr/local/ssl/csr.pem -keyfile /usr/local/ssl/demoCA/private/cakey.pem -cert /usr/local/ssl/demoCA/cacert.pem -out /usr/local/ssl/cert.pem

 コマンドを実行すると、鍵の作成時に指定したパスフレーズの入力を求められる。パスフレーズを入力すると、証明書に記載する情報(入力した国別コードや組織名称など)が表示され、本当に証明書を作成するかどうか確認される。そこで「y」を入力すれば、証明書が作成される仕組みだ。作成されたファイルを参照してみると、その中には証明書の情報として、組織名などが記載されていることが分かるだろう。

 なお、ここで使っているオプションは、

-inオプション
作成した申請書ファイル

-keyfileオプション
認証機関の秘密鍵ファイル

-certオプション
認証機関の証明書ファイル

-outオプション
作成した証明書ファイル

である。

SSLを使うためのApacheの設定

 サーバの鍵ファイルと証明書ファイルが準備できたら、いよいよApacheの設定を行う。Apacheにmod_sslが導入されていれば、Apacheの設定ファイル(httpd.conf)にはSSLに関するディレクティブが用意されているはずだ。その中の「SSLCertificateFile」ディレクティブには、サーバの署名付き証明書ファイルを指定する。また、「SSLCertificateKeyFile」ディレクティブには、サーバの鍵ファイルを指定する。この2つのディレクティブを設定すれば、基本的な設定は終了である。

 後は、ApacheをSSLモードで起動する。SSLモードで起動するとは、apachectlに対しパラメータstartsslを与えるということだ。つまり、これまで「apachectl start」としていたところを、「apachectl startssl」とするのである。

 ApacheをSSLモードで起動したら、Webブラウザからアクセスしてみよう。このとき、URLは「http://」ではなく「https://」になることに注意すること。無事にアクセスできれば、WebブラウザはSSLによる通信を行おうとする。独自の認証機関を使った場合、Webブラウザは警告を発するはずだ。これは、サーバから送信された証明書がWebブラウザに登録されていないものだからである。

 Netscape Navigatorの場合、画面1のような警告が最初に表示される。

画面1 未登録証明書を認識すると、このウィンドウが表示される

 そこから進んでいくと、この証明書を受け入れるかどうかを尋ねられる(画面2)。

画面2 証明書の処理方法の選択
画面3

 ここで受け入れると、Webページが表示されるはずだ。このとき、画面3のように画面左下の鍵マークがロック状態になっていることを確認しておきたい。

 このように、証明書を受け入れるとWebブラウザに登録される。従って、それ以降の通信からは警告を出さなくなる。受け入れた証明書は、Webブラウザのメニューから確認することもできる(画面4)。無事にSSLで通信できることを確認したら、後は通常のApacheの設定と同じである。暗号化する対象のコンテンツを決定し、その設定を加えていけばよい。

画面4 証明書の編集画面(画像をクリックすると拡大表示します)

 次回は、Apacheのログ管理について紹介する。