サーバいじくり雑記

2014年7月17日

MySQLデータベースとの通信をSSL暗号化する

Filed under: ソフト, Database — bompopo @ 6:00 PM

管理してるサーバの移転でダウンタイムを最小化するためにレプリケーション機能を使いたくなったのです。しかし普通にレプリケーションした場合は生情報が通信経路に流れてしまうので、そこでSSL暗号化通信ですよ。

通信をSSL暗号化する設定

サーバ証明書だけでも自己署名してやればそれのみでSSL通信可能ですが、他の証明書作成にも使えるので自前CAは作っておきたいですね。使い回しましょう。

まずCAを作成します。

$ sudo mkdir -p /usr/local/etc/ssl/mysql/
$ sudo chown mysql:mysql /usr/local/etc/ssl/mysql/                 # ←ハマリポイントその1
$ cd /usr/local/etc/ssl/mysql/
$ sudo openssl genrsa -out ca-key.pem 2048
$ sudo chmod 400 ca-key.pem
$ sudo openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca-cert.pem \
  -subj '/DC=example/DC=com/CN=CA'                                 # ←ハマリポイントその2
$ sudo chmod 444 ca-cert.pem
$ ls -l
-r--------   1 root   wheel  1667  xx xx xx:xx ca-cert.pem
-r--r--r--   1 root   wheel  1675  xx xx xx:xx ca-key.pem

サーバ証明書を作成し、CAで署名します。

$ cd /usr/local/etc/ssl/mysql/
$ sudo -u mysql openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-req.pem \
  -subj "/DC=example/DC=com/CN=MySQL\ Server"                      # ←ハマリポイントその2
$ sudo -u mysql openssl rsa -in server-key.pem -out server-key.pem # ←ハマリポイントその3
$ sudo chmod 444 server-key.pem
$ sudo openssl x509 -req -in server-req.pem -days 3650 -CA ../ca-cert.pem -CAkey ../ca-key.pem \
  -out server-cert.pem -set_serial 01
$ sudo chown mysql:mysql server-sert.pem
$ sudo chmod 444 server-sert.pem
$ ls -l
-r--r--r--  1 mysql  mysql  1318  xx xx xx:xx server-cert.pem
-r--r--r--  1 mysql  mysql  1679  xx xx xx:xx server-key.pem
-rw-r--r--  1 mysql  mysql  1074  xx xx xx:xx server-req.pem

CAとサーバ証明書の準備はできました。
次はMySQLサーバの設定に入ります。my.cnfに以下を記述。

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

SSL接続するMySQLのユーザを作ります。

$ mysql -u root --password='password' -h localhost -e \
  'GRANT ALL ON db_name.* TO ssluser@hostname IDENTIFIED BY "sslpassword" REQUIRE SSL ; FLUSH PRIVILEGES;'

ポイントは”REQUIRE SSL”の部分です。これでこのユーザは接続時にSSLが必須となります。

mysqldを再起動し、SSLが有効化されていることを確認します。

$ service mysql-server restart
$ mysql -u root --password='password' -h localhost -e \
  "show global variables like '%ssl%';"
+---------------+---------------------------------------------------------------+
| Variable_name | Value                                                         |
+---------------+---------------------------------------------------------------+
| have_openssl  | YES                                                           |
| have_ssl      | YES                                                           |
| ssl_ca        | /usr/local/etc/ssl/ca-cert.pem                        |
| ssl_capath    |                                                               |
| ssl_cert      | /usr/local/etc/ssl/mysql/mysql-master-server-cert.pem |
| ssl_cipher    |                                                               |
| ssl_key       | /usr/local/etc/ssl/mysql/mysql-master-server-key.pem  |
+---------------+---------------------------------------------------------------+

注目はhave_opensslとhave_sslの部分。ここがYESになっているとSSL通信が可能です。

実際にSSL接続して暗号化されているか確認します。
mysqlコマンドで接続する際には通常時と違い–ssl-ca引数でCA証明書ファイルを指定します。

$ mysql -u ssluser --password='sslpassword' -h hostname --ssl-ca=/usr/local/etc/ssl/mysql/ca-cert.pem -e \
 "SHOW STATUS LIKE 'Ssl_cipher';"
+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| Ssl_cipher    | DHE-RSA-AES256-SHA |
+---------------+--------------------+

暗号化モードを表す文字列がValueに入っています。暗号化されていない場合はValueには文字列が入っていません。

さて、一連の手順を説明したところでハマリポイントの説明をします。

ハマリポイントその1

MySQLサーバが使用するサーバ証明書を配置するディレクトリの所有権はmysqldを実行するユーザでなくてはなりません。
こんな感じでエラーが出てSSLが有効になりません。

SSL error: Unable to get certificate from '/usr/local/etc/ssl/mysql/server-cert.pem'
[Warning] Failed to setup SSL
[Warning] SSL error: Unable to get certificate
ハマリポイントその2

CAとサーバ証明書は別々のCNを指定しましょう。これは証明書を検証する際にその中でユニークである必要があるのです。

ハマリポイントその3

鍵をRSAモードに変換しないとMySQLは読み込んでくれません。(実際はヘッダとフッターの一部にRSAという文字列を加えるだけの変換なのですが(笑)

おまけ:クライアント証明書認証もしたい

上記に加えてクライアント側にクライアント証明書のセットアップとサーバ側の接続ユーザをSSL条件ではなくX509条件にしておきます。

クライアント証明書の作り方はサーバ証明書と一緒なので記述はしません。
DBのユーザ作成では”REQUIRE X509″を指定します。

$ mysql -u root --password='password' -h localhost -e \
'GRANT ALL ON db_name.* TO ssluser@hostname IDENTIFIED BY "sslpassword" REQUIRE X509 ; FLUSH PRIVILEGES;'

接続する際には–ssl-caに加えて–ssl-certと–ssl-keyを使ってクライアント証明書を指定します。

$ mysql -u ssluser --password='sslpassword' -h hostname --ssl-ca=/usr/local/etc/ssl/ca-cert.pem
--ssl-cert=/usr/local/etc/ssl/mysql/client-cert.pem \
--ssl-key=/usr/local/etc/ssl/mysql/client-key.pem
広告

コメントする »

まだコメントはありません。

RSS feed for comments on this post. TrackBack URI

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。