PHPでMySQLを扱うに当たって、SSL通信を行うときのメモ

細かい説明は省きますが、まずはSSL証明書を作成する。
注意することとしては証明書を作成する際にcommon nameとかを適当に書くとあとで泣きを見る。

mkdir /etc/mysql-ssl
cd /etc/mysql-ssl
# CAキーの作成
openssl genrsa -out ca-key.pem 2048
# CA証明書を作成
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca-cert.pem
# MySQLサーバーの秘密鍵とCSRの作成
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-req.pem
# MySQLサーバーの証明書作成
openssl x509 -req -in server-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -out server-cert.pem -set_serial 01

/etc/my.cnf [mysqld]にSSL設定を追記

[mysqld]
ssl-ca=/etc/mysql-ssl/ca-cert.pem  
ssl-cert=/etc/mysql-ssl/server-cert.pem  
ssl-key=/etc/mysql-ssl/server-key.pem

MySQLを再起動

# OS が違う場合は適宜コマンドを変更してください
service mysqld restart

コマンドラインからMySQLにログインしてSSL通信が有効になっているか確認。
下記のコマンドを入力した結果が同じようになればSSL通信が有効になっている。

mysql> SHOW VARIABLES LIKE '%ssl%'
+---------------+--------------------------------+
| Variable_name | Value                          |
+---------------+--------------------------------+
| have_openssl  | YES                            |
| have_ssl      | YES                            |
| ssl_ca        | /etc/mysql-ssl/ca-cert.pem     |
| ssl_capath    |                                |
| ssl_cert      | /etc/mysql-ssl/server-cert.pem |
| ssl_cipher    |                                |
| ssl_key       | /etc/mysql-ssl/server-key.pem  |
+---------------+--------------------------------+

SSL通信するユーザーを作成する((例) ユーザー名: user , パスワード: password ホスト:ローカルホスト)

GRANT USAGE ON *.* TO 'user'@'localhost' IDENTIFIED BY 'password' REQUIRE SSL;

SSL通信を使用してコマンドラインでログインする(例)
クライアント証明書を必要としない設定なのでCA証明書を指定するか、cipherの指定でログインできる。

mysql -h localhost -u user -p password --ssl-ca=/etc/mysql-ssl/ca-cert.pem
mysql -h localhost -u user -p password --ssl-cipher=DHE-RSA-AES256-SHA

ログインしてSSL通信が有効になっているか確認する。
Valueに以下の値が入っていればSSL通信している。

mysql> SHOW STATUS LIKE 'Ssl_cipher';
+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| Ssl_cipher    | DHE-RSA-AES256-SHA |
+---------------+--------------------+

ここまでで、ようやくPHPでSSL通信を使う下準備ができたので、mysqliクラスを拡張してSSL通信を使う。

class foo_mysqli extends mysqli {
    const MYSQL_SERVER_URI = 'localhost';
    const MYSQL_USER_NAME = 'user';
    const MYSQL_USER_PASSWD = 'password';
    const MYSQL_USE_DB = 'test';
	
    public function __construct($host, $user, $pass, $db) {
        parent::init();
        parent::ssl_set(
            // 未使用のパラメータにはNULLを入力
            NULL, // 鍵ファイルへのパス
            NULL, // cert証明書ファイルへのパス
            NULL, // CAファイルへのパス(ca-cert.pem 指定)
            NULL, // 信頼された SSL CA 証明書が PEM フォーマットで格納されているディレクトリへのパス。
            "DHE-RSA-AES256-SHA" // SSL の暗号化に使用可能な暗号形式の一覧。
        );

        // オートコミットをオフにする初期設定
        // 意図せずにロールバックされたりするときはこの設定をしないか、明示的にcommitすること
        if (!parent::options(MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT = 0')) {
            die('Setting MYSQLI_INIT_COMMAND failed');
        }
        if (!parent::options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
            die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
        }
	if (!parent::real_connect($host, $user, $pass, $db)) {
            die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
        }
    }
}

// 使用例
$mysqli = foo_mysqli(
                foo_mysqli::MYSQL_SERVER_URI,
                foo_mysqli::MYSQL_USER_NAME,
                foo_mysqli::MYSQL_USER_PASSWD,
                foo_mysqli::MYSQL_USE_DB
          );
echo 'Success... ' . $mysqli->host_info . "\n";
$mysqli->close();

なお、Windows版xamppで若干はまったのが、php.iniの設定
SSLのモジュールがコメントアウトされているので、コメントアウトを解除してapacheを再起動する。

extension=php_openssl.dll

これで基本的なPHPでのMySQL、SSL通信ができるようになった。
次は、クライアント証明書を必要とする設定を書こうと思う。

あ、、、新年明けましておめでとうござます(笑)