読者です 読者をやめる 読者になる 読者になる

ようへいの日々精進XP

よかろうもん

MySQL で SSL での接続を有効にする一部始終(1)

要件

  • MySQL でグローバル IP をまたぐレプリケーションをやってみたい
  • その場合、通信は SSL で暗号化したい
  • 手始めに同一ホスト内から SSL を使って接続を試してみる

環境

手順

MySQL のインストール

yum install -y mysql-server

Chef のレシピ的には以下で...

package "mysql-server" do
        action :install
end

service "mysql_service" do
        case node["platform"]
        when "CentOS","RedHat","Fedora","amazon"
                service_name "mysqld"
        else
                service_name "mysql"
        end
        supports :status => true, :restart => true, :reload => true
        action [ :enable, :start ]
end

MySQL 上の SSL 状態の確認

mysql> SHOW VARIABLES LIKE '%ssl%';  
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| have_openssl  | DISABLED |
| have_ssl      | DISABLED |
| ssl_ca        |          |
| ssl_capath    |          |
| ssl_cert      |          |
| ssl_cipher    |          |
| ssl_key       |          |
+---------------+----------+
7 rows in set (0.00 sec)

SSL を使う為の準備

  • 注意点
    • Common Name は CA と MySQL サーバーで分けること...
CA のキーを生成
mkdir /etc/mysql-ssl
cd /etc/mysql-ssl
openssl genrsa -out ca-key.pem 2048
CA の証明書を作成
openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem
MySQL サーバーの秘密鍵と CSR の作成
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem
MySQL サーバーの証明書作成
openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -out server-cert.pem -set_serial 01

my.cnf への設定し、MySQL の再起動を行う

[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
/etc/init.d/mysqld restart

改めて MySQL 上の SSL 状態の確認

mysql> SHOW VARIABLES LIKE '%ssl%';
--------------
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  |
+---------------+--------------------------------+
7 rows in set (0.00 sec)

SSL でアクセスする為のユーザーを作る

GRANT ALL PRIVILEGES ON *.* TO ${your_user}@localhost IDENTIFIED BY '${your_pass}' REQUIRE SSL;
FLUSH PRIVILEGES;

SSL 用ユーザーでアクセスする

  • CA の証明書を指定して接続する
mysql -h localhost -u ${your_user} --ssl-ca=/etc/mysql-ssl/ca-cert.pem -p  
  • SSL で接続していることを確認する場合には、以下のクエリで確認する。非 SSL 通信の場合には Value には値が入らない。
show status like'Ssl_cipher';
--------------
SHOW STATUS LIKE 'Ssl_cipher'
--------------

+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| Ssl_cipher    | DHE-RSA-AES256-SHA |
+---------------+--------------------+
1 row in set (0.00 sec)

検証

そもそもホントに SSL で接続してんのか?

  • 一応、設定は出来たものの接続の暗号化は行われているのかを確認する
  • tcpdump でキャプチャしながら適当なクエリーを投げてみる
  • tcpdump は以下のオプションにてキャプチャを行う
tcpdump -nxX -s 2000 port 3306 -ilo
SSL 接続無し

f:id:inokara:20130429022517p:plain

SSL 接続有り

f:id:inokara:20130429022526p:plain

上記の通り、SSL 経由での接続の場合、クエリ等のサーバーとのやりとりは暗号化されていることが確認出来た。

まとめ

  • SSL 接続は意外に簡単に試すことが出来た。
  • 但し、SSL 接続に必要な証明書ファイル等の作成の際、Common Name の設定を適当(当初は同じ Common Name にしていた)に設定すると以下のようなエラーが出ることがあるので注意する。
ERROR 2026 (HY000): SSL connection error: error:00000001:lib(0):func(0):reason(1)