日別アーカイブ: 2011年2月10日

SSL設定

物販サイトとか、最近の商用サイトではSSL(HTTPS)の設置はほぼ常識だろう。
未だに、一般ユーザにはHTTPSの効果がわからない人もいるようだけど、少しでも知識があれば秘密情報を送るのにHTTPSが必須なのがわかるだろう。
単純に言えば、HTTPSは電子証明書を使って、接続先のサーバ名が証明書発行先の名前と一致することを保証し、かつ、ブラウザからサーバまでの通信が暗号化される。
電子証明書は、最初から端末にいくらかの物が保存されている。 これらの証明書の発行元を信頼された証明書発行機関として、その機関が発行した証明書を信頼できると判断する。
新たに接続したサイトの証明書が、信頼された証明書発行機関から発行された証明書であれば、接続したサイトも信頼できる(電子証明書にはサーバのアドレスが記述されている)
従って、携帯電話等では端末によって初期の証明書が異なり、あまり有名ではない発行機関が発行した証明書が信頼できない証明書と判断されることがある。
また、外部の証明書発行機関に依存せず、最初から自分で証明書を発行することも出来る(いわゆるオレオレ証明書) この場合、サイトの確認に利用するためには、信頼された方法で証明書を端末に登録しておく必要がある(例えば、USBメモリなどに保存してPCに登録する等だが、一度目に接続したサイトを信頼するなら、初回接続時に証明書を登録しても良い)
しかしながら、特定のクライアントに向けたサイト(契約業者向けサイトであるとか)でもない限り、信頼された機関から発行されていない証明書の使用は、逆に信頼度を下げる結果になるだろう(最近のIEやFirefox等のブラウザは、証明書が信頼できませんとでかでかと表示してクライアントに警告する)
それでもオレオレ証明書を使用するのは、通信経路の暗号化が可能であると言うポイントにある。 個人情報をHTTPで送信すれば、ネットワーク上にパケット盗聴器を配置したり、無線LANの電波を盗聴する等することで簡単に情報を盗まれてしまう。 しかし、HTTPSでは、ブラウザの内部からサイト内までの区間は暗号化されているので、無線LAN電波を盗聴されても、情報を入手することは困難である。
そんなわけで、個人サイト等で出先からのアクセスを保護する目的などでオレオレ証明書が使われることがある。
まぁ、有料の信頼された証明書を取得するのがベストであるのは確かだが。

実際にSSLを使用する設定。
基本的に、ServersManに入っているApacheは最初からSSLが使えるので、証明書の準備と設定ファイルを記述するだけで良い。

証明書の準備
A,オレオレ証明書を使う
B,信頼された証明書を使う
どちらのパターンでも、秘密鍵ファイルの作成は共通で

openssl genrsa -des3 2048 -out /etc/pki/tls/private/hoge.pem

DES3(従来のDES暗号を3回かける方式)で2048ビット長の鍵を作る設定 ※古いサイトでは1024ビットを示しているところもあるが、現在は1024ビットでは強度不足とされている。
このとき、秘密鍵を保護するパスフレーズの入力を促されるので、適当なものを設定する。

Aパターンの場合、この秘密鍵を元にサイト証明書(CRT)を作成する。

openssl req -new -x509 -days 365 -key /etc/pki/tls/private/hoge.pem -out /etc/pki/tls/certs/hoge.crt

この場合は、365日間有効なX509証明書を先ほどの秘密鍵を使って作成する。 有効期間は長くても良いが、パスワードのように定期的に更新するのが一般的。
(後記共通項へ)

Bパターンの場合、この秘密鍵を使って証明書要求(CSR)を作成する。

openssl req -new -key /etc/pki/tls/private/hoge.pem -out hoge.csr

先ほどの秘密鍵を使って証明書要求を作成する。 A/Bともコマンドは似ているが、Aは証明書自体を作り、Bは証明書を要求するための中間情報を作成している。

<共通項>
先ほどのパスフレーズや、サイト情報などの入力を促されるので入力していく。 項目名はビルドにより多少異なるので環境毎に読み替え

Enter pass phrase for /etc/pki/tls/private/hoge.pem:先ほどのパスフレーズ
Country Name (2 letter code)[GB]:JP
#2文字の国コードで、日本ならJP
State or Province Name (full name) [Berkshire]:Kanagawa
#都道府県
Locality Name (eg, city) [Newbury]:Yokohama
#市区町村
Organization Name (eg, company) [My Company Ltd]:hogehoge Corp
#団体名(個人の場合はフルネーム等)
Organizational Unit Name (eg, section) []:online sales div
#部署名だが、団体名までが同じ複数の証明書を取得する場合に、この項目を変更して取得する。
Common Name (eg, your name or your server’s hostname) []:ssl.hoge.net
#サイトの完全名を入力する。 サイト確認する為に使われるアドレスになる(異なるアドレスのサイトで証明書を使うと警告が出るので、運用アドレスにしっかりあわせる)
これ以降のEmail Address等の項目は任意でOK

これで証明書ファイルか、証明書要求ファイルが出来る。
Aならこれで証明書準備完了。 Bの場合は、作成されたhoge.csrの中身をSSL証明書発行機関の発行要求Webフォームやメールに添付したりして証明書を要求すると、証明書ファイルが送られてくるので、Aの/etc/pki/tls/certs/hoge.crt等のように配置する。
証明書と間違えて証明書要求ファイルを配置するとApacheがエラーで起動できなくなるし、証明機関に証明書を送っても証明書が作成できないので注意。

Apacheの設定を行う。
ApacheのSSL設定ファイルは↓がデフォルト
/etc/httpd/conf.d/ssl.conf

#HTTPSを受け入れるためにバーチャルホスト設定を使う。
<VirtualHost 210.170.xxx.yyy:443>
#ServerNameディレクティブで完全なホスト名を設定して、証明書のCommon Nameと一致させる。
ServerName ssl.hoge.net
#サイト証明書ファイルを設定する
SSLCertificateFile /etc/pki/tls/certs/hoge.crt
#秘密鍵ファイルを設定する
SSLCertificateKeyFile /etc/pki/tls/private/hoge.pem

この状態でApacheを起動しようとすると、秘密鍵のパスフレーズを要求されるようになるので、自動起動したい場合には
ssl.conf

SSLPassPhraseDialog exec:/root/sslkey.sh

コマンドの標準出力をパスフレーズとして利用しようとするので、echo ‘passphrase’等とシェルに記述して実行権限をつけておけば自動起動できるようになる。

(432)

カテゴリー: サーバ設定 | コメントをどうぞ

PHPとMySQLと文字コードと

 最近の流れとして、文字コードと言えばUTF8って感じが強い(携帯などではSJISもあるけど)
 しかしながら、CentOSや海外から拾ったコンパイル済みPHPの従来型MySQL関数って、コネクト時のクライアントエンコーディングがlatin1になっている。
 この値は、mbstringとか色々変えても変わらず、自前でビルドしないとダメっぽい。
 他方、MySQLサーバではmy.cnfに

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

等と入れてやるとUTF8で回るし、個別にデータベースやテーブルを作るときに指定してやることも出来る(現在のMySQLではdefault-character-setは推奨外) コマンドラインのmysqlもmy.cnfに

[mysql]
default-character-set=utf8

とかすれば、UTF8で繋がる。
 それでも、PHPクライアントでmysql_connectして、mysql_client_encodingで引っ張るとlatin1になるし、SHOW VARIABLESクエリの戻り値もクライアントやリザルトはlatin1になってしまう。
 このため、最近のMySQLとPHP(5.2.3以降)の組み合わせではmysql_set_charsetと言う関数を使ってクライアントのエンコーディングを設定してやることが出来る(古いバージョンでは、SET NAMESクエリを発行して変更できるが、サニタイズ関連の動作が期待と異なる事になったり、タイムアウトしたDB接続を自動再接続したときにエンコーディングが元に戻る様だ)
 しかし、実際の所は、このあたりの設定をせずともPHPから処理する限りは、UTF8の文字列を普通にDBに格納して取得も出来てしまう。 これは、エンコーディング設定が同じなら同じ方法で文字列を化けさせているから、化けた文字列を格納しても、取り出し時に逆処理で戻してしまい、外見上は問題なく動作してしまっているのだ。
これをデータベースマネージャなどでテーブル表示すると化け化けの文字列であるから、管理コマンドや、別のアプリケーションからDBを参照したときに問題が起きるし、検索処理や関数などで予想外の動作をする可能性もあるので、エンコーディング設定はしっかり行っておかなければならない。

 my.cnfの[mysqld]でskip-character-set-client-handshakeを設定してやると、サーバの標準キャラクタセットをクライアント値と同期しないので、mbstring.internal_encodingをutf8にしたPHPとutf8設定のMySQLの組み合わせでutf8で格納されて、データベースマネージャなどでもちゃんと表示できるので、この方法を示しているページもあるが、この状態でもmysql_client_encodingはlatin1で、SHOW VARIABLES結果はutf8設定というおかしな状態になるので、これも予想外の動作をする可能性があるわけで、正しく動作させたければ、毎回mysql_set_charsetを実行するか、ソースからPHPをビルドして、標準エンコーディングをutf8にするなどした方が良いと思う。
 また、skip-character-set-client-handshake設定してしまうと、[mysql]のdefault-character-setと整合を取らなくなるので注意が必要(例えば、mysqlをdefault-character-set=ujisで動かしてると、mysqlコマンドで接続した段階ではクライアントがujisで、サーバはutf8クライアントと認識しているのでキャラクタセットの齟齬で文字化けが生じる)

(467)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP], PHP | コメントをどうぞ