LoginSignup
46
46

More than 5 years have passed since last update.

MySQLでSSLクライアント証明書を使う

Posted at

MySQLでSSLクライアント証明書を使ってみたくなったので試してみました。

MySQL のバージョンとか

  • CentOS 6.4
  • MySQL 5.5.34 (mysql-server-5.5.34-1.el6.remi.x86_64)

CA証明書とサーバ証明書を作成

証明書を保存するディレクトリを作成します。
どこでもいいのですがとりあえず /etc/mysql/ssl/ にします。

# mkdir -p /etc/mysql/ssl/
# cd /etc/mysql/ssl/

CAの秘密鍵と自己署名証明書を作成します。

# openssl req -new -out ca.crt -keyout ca.key -x509 -days 3650 -newkey rsa:2048 -nodes -subj "/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=OreOre CA"

Generating a 2048 bit RSA private key
..............................
writing new private key to 'ca.key'
-----

秘密鍵のパーミッションを変更します。0644 のままでも動作しますが変更しておいて損はないでしょう。

# chmod 600 ca.key

サーバ証明書の秘密鍵とCSRを作成します。CN(example.jp)にはサーバのホスト名を指定します。

# openssl req -new -out server.csr -keyout server.key -newkey rsa:2048 -nodes -subj "/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=example.jp"

Generating a 2048 bit RSA private key
..............................
writing new private key to 'server.key'
-----

秘密鍵のパーミッションとオーナーをを変更します。パーミッションを変更する場合 mysqld から読めるようにオーナーの変更も必要です。

# chmod 600 server.key
# chown mysql: server.key

サーバ証明書を作成します。

# openssl x509 -req -days 3650 -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial

Signature ok
subject=/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=example.jp
Getting CA Private Key

クライアント証明書の秘密鍵とCSRを作成し、CSRをサーバに送信します。 この作業はクライアント側で行います。

$ openssl req -new -out client.csr -keyout client.key -newkey rsa:2048 -nodes -subj "/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=ore@example.jp"

Generating a 2048 bit RSA private key
..............................
writing new private key to 'client.key'
-----

$ chmod 600 client.key
$ scp client.csr example.jp:/tmp/

サーバ側でクライアント証明書を作成します。

# cd /etc/mysql/ssl/
# openssl x509 -req -days 3650 -in /tmp/client.csr -out /tmp/client.crt -CA ca.crt -CAkey ca.key -CAcreateserial

Signature ok
subject=/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=ore@example.jp
Getting CA Private Key

クライアント側にCA証明書とクライアント証明書をダウンロードします。

$ scp example.jp:/etc/mysql/ssl/ca.crt ./
$ scp example.jp:/tmp/client.crt ./

MySQL の設定

MySQLでサーバ証明書を設定します。
とりあえずSSL通信だけを試すので ssl-ca は設定しません。

my.cnf
ssl-key  = /etc/mysql/ssl/server.key
ssl-cert = /etc/mysql/ssl/server.crt

設定を反映します。

# service mysqld restart

設定が有効になっていることを確認します。

# mysql -e "SHOW VARIABLES LIKE '%ssl%'"

次のように出力されるはずです。

+---------------+---------------------------+
| Variable_name | Value                     |
+---------------+---------------------------+
| have_openssl  | YES                       |
| have_ssl      | YES                       |
| ssl_ca        |                           |
| ssl_capath    |                           |
| ssl_cert      | /etc/mysql/ssl/server.crt |
| ssl_cipher    |                           |
| ssl_key       | /etc/mysql/ssl/server.key |
+---------------+---------------------------+

SSLが必須なユーザーを作成します。

# mysql

次のように作成します。

GRANT ALL ON test.* TO ssluser@'%' IDENTIFIED BY 'pass' REQUIRE SSL;

SSLで接続

まずは普通に接続してみます。ssluser はSSLが必須なので弾かれます。

$ mysql -h example.jp -u ssluser -ppass
ERROR 1045 (28000): Access denied for user 'ssluser'@'192.0.2.101' (using password: YES)

--sslオプションを指定してみます。が、これだけだとSSL通信にはなりませんでした。

$ mysql -h example.jp -u ssluser -ppass --ssl
ERROR 1045 (28000): Access denied for user 'ssluser'@'192.0.2.101' (using password: YES)

SSLで接続するためには --ssl-cipher--ssl-ca--ssl-cert の指定が必要です。

--ssl-cert はクライアント証明書を指定するものなので今は使いません。ひとまず他の2つで接続してみます。

$ mysql -h example.jp -u ssluser -ppass --ssl-cipher=DHE-RSA-AES256-SHA
$ mysql -h example.jp -u ssluser -ppass --ssl-ca=ca.crt

どちらでも接続できました。

--ssl-ca を指定する場合はサーバ証明書がそのCA証明書で署名されている必要があります。
なので適当な自己署名証明書を指定しても接続できません。

$ openssl req -new -out another.crt -keyout another.key -x509 -days 3650 -newkey rsa:2048 -nodes -subj "/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=OreOre Another CA"

Generating a 2048 bit RSA private key
.................................
writing new private key to 'another.key'
-----

$ mysql -h example.jp -u ssluser -ppass --ssl-ca=another.crt
ERROR 2026 (HY000): SSL connection error: error:00000001:lib(0):func(0):reason(1)

--ssl-verify-server-cert を追加で指定するとサーバ証明書の CommonName と接続先ホスト名の比較も行われます。
例えば、次のように IP アドレスを指定すると接続できません。

$ mysql -h 192.0.2.100 -u ssluser -ppass --ssl-ca=ca.crt --ssl-verify-server-cert
ERROR 2026 (HY000): SSL connection error: SSL certificate validation failure

サーバ証明書の CommonName と同じホスト名で接続する必要があります。

$ mysql -h example.jp -u ssluser -ppass --ssl-ca=ca.crt --ssl-verify-server-cert

クライアント証明書を使って接続

次にクライアント証明書を使ってみます。

まずは my.cnf でクライアント証明書に署名したCA証明書を ssl-ca に指定します。

my.cnf
ssl-key  = /etc/mysql/ssl/server.key
ssl-cert = /etc/mysql/ssl/server.crt
ssl-ca   = /etc/mysql/ssl/ca.crt

設定を反映します。

# service mysqld restart

設定が反映されていることを確認します。

# mysql -e "SHOW VARIABLES LIKE '%ssl%'"

次のように表示されます。

+---------------+---------------------------+
| Variable_name | Value                     |
+---------------+---------------------------+
| have_openssl  | YES                       |
| have_ssl      | YES                       |
| ssl_ca        | /etc/mysql/ssl/ca.crt     |
| ssl_capath    |                           |
| ssl_cert      | /etc/mysql/ssl/server.crt |
| ssl_cipher    |                           |
| ssl_key       | /etc/mysql/ssl/server.key |
+---------------+---------------------------+

クライアント証明書が必要なユーザーを作成します。

$ mysql

次のように作成します。

GRANT ALL ON test.* TO ssluser@'%' IDENTIFIED BY 'pass' REQUIRE X509;

クライアント証明書を使わずに接続してみます。ssluser はクライアント証明書が必要なので接続できません。

$ mysql -h example.jp -u ssluser -ppass --ssl-cipher=DHE-RSA-AES256-SHA
ERROR 1045 (28000): Access denied for user 'ssluser'@'192.0.2.101' (using password: YES)

$ mysql -h example.jp -u ssluser -ppass --ssl-ca=ca.crt
ERROR 1045 (28000): Access denied for user 'ssluser'@'192.0.2.101' (using password: YES)

$ mysql -h example.jp -u ssluser -ppass --ssl-ca=ca.crt --ssl-verify-server-cert
ERROR 1045 (28000): Access denied for user 'ssluser'@'192.0.2.101' (using password: YES)

次のようにクライアント証明書を指定すれば接続出来ます。

$ mysql -h example.jp -u ssluser -ppass --ssl-cert=client.crt --ssl-key=client.key

もちろん --ssl-ca--ssl-verify-server-cert を一緒に指定することも出来ます。

$ mysql -h example.jp -u ssluser -ppass --ssl-ca=ca.crt --ssl-verify-server-cert --ssl-cert=client.crt --ssl-key=client.key

その他

今回はCA証明書とサーバ証明書を別にしましたが、同じでも大丈夫です。

その場合は次のようにサーバ証明書を自己署名で作成し、

$ openssl req -new -out server.crt -keyout server.key -x509 -days 3650 -newkey rsa:2048 -nodes -subj "/C=JP/ST=Tokyo/L=SonoHen/O=OreOre/OU=Dev/CN=example.jp"

クライアント証明書にはサーバ証明書で署名して、

$ openssl x509 -req -days 3650 -in /tmp/client.csr -out /tmp/client.crt -CA server.crt -CAkey server.key -CAcreateserial

my.cnf でCA証明書にサーバ証明書を指定して、

my.cnf
ssl-key  = /etc/mysql/ssl/server.key
ssl-cert = /etc/mysql/ssl/server.crt
ssl-ca   = /etc/mysql/ssl/server.crt

クライアント側は --ssl-ca にサーバ証明書を指定します。

$ mysql -h example.jp -u ssluser -ppass --ssl-ca=server.crt --ssl-verify-server-cert --ssl-cert=client.crt --ssl-key=client.key
46
46
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
46