はじめに
昨今のWebサービスでは常時SSL/TLS化が当たり前となっています。
HTTPだけに限らず、リモートとの通信をする場合はできる限り暗号化して、セキュリティを高めていきたいところです。
そこで改めてMySQLでSSL/TLSについて確認してみます。
現在では脆弱性等の問題でSSLを使用することはないと思いますが、便宜上まとめてSSL/TLSと表記します。
SSL(Secure Socket Layer)/TLS(Transport Layer Security)
まず簡単にSSL/TLSの概要として
【暗号鍵を使いデータを暗号化し、メッセージ認証コードを使用し改ざんを検出し、デジタル署名で正当な相手との通信をする】
というものになるかと思います。
これらによって下記のようなセキュリティ向上が期待できます。
(自己署名証明書ではその限りではありません)
MySQLでの暗号化通信
現在MySQL5.7を公式リポジトリからダウンロードしてインストールし、起動すると
デフォルトで証明書が用意され、SSL/TLSが有効化されています。
(5.6では手動で証明書を用意し、有効化する必要があります。)
試しに5.7.21をリポジトリからインストールし、起動します。
1 2 3 4 |
$curl -LO https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm $sudo yum install -y mysql57-community-release-el7-11.noarch.rpm $sudo yum install -y mysql-server $sudo systemctl start mysqld |
サーバー起動後、データディレクトリを確認すると各種鍵/証明書が用意されます。
1 2 3 4 5 6 7 8 9 10 |
$sudo ls /var/lib/mysql | grep -i '.pem' ca-key.pem ca.pem client-cert.pem client-key.pem private_key.pem public_key.pem server-cert.pem server-key.pem |
各ファイルの説明
ca-cert.pem: サーバー側とクライアント側で –ssl-ca への引数として使用(CA 証明書を使用する場合は、両側で同じものを指定する必要)
server-cert.pem、server-key.pem: サーバー側で –ssl-cert および –ssl-key への引数として使用
client-cert.pem、client-key.pem: クライアント側で –ssl-cert および –ssl-key への引数として使用
https://dev.mysql.com/doc/refman/5.6/ja/creating-ssl-certs.htmlより
ではリモートから接続して暗号化されているか確認して見ましょう
(初期のパスワード設定は割愛します)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
mysql> SHOW GLOBAL VARIABLES LIKE '%ssl%'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | have_openssl | YES | | have_ssl | YES | | ssl_ca | ca.pem | | ssl_capath | | | ssl_cert | server-cert.pem | | ssl_cipher | | | ssl_crl | | | ssl_crlpath | | | ssl_key | server-key.pem | +---------------+-----------------+ 9 rows in set (0.00 sec) mysql> \s # 以下抜粋 -------------- mysql Ver 14.14 Distrib 5.7.21, for osx10.13 (x86_64) using EditLine wrapper Connection id: 13 Current database: SSL: Cipher in use is DHE-RSA-AES256-SHA Server version: 5.7.21 MySQL Community Server (GPL) Protocol version: 10 Threads: 1 Questions: 46 Slow queries: 0 Opens: 113 Flush tables: 1 Open tables: 106 Queries per second avg: 0.011 -------------- |
ちゃんと設定されていますね。
では、実際のパケットでも確認してみましょう。
サーバー側で「tcpdump」を使いキャプチャ出来るように準備します。
※tcpdumpはネットワーク上に流れるパケットをキャプチャ出来る便利ツールです
1 |
$sudo tcpdump -X port 3306 |
リモートのクライアントから接続してみます。
まずは暗号化されていない状態で確認。
1 2 3 4 5 6 7 8 9 10 11 12 |
$mysql -uユーザー名 -p -hホスト名 --skip-ssl mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.03 sec) |
ではサーバー側で確認してみます。
セッションをつなぐ際のログが流れていますが、コマンド実行時のパケットを抜粋すると下記のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
0x0000: 4500 0047 0000 4000 2706 b1f0 999c f76e E..G..@.'......n 0x0010: ac1a 649b c8cd 0cea 9489 39fc 62c8 5cd1 ..d.......9.b.\. 0x0020: 8018 1010 42f4 0000 0101 080a 32ec ab64 ....B.......2..d 0x0030: 0050 2bd8 0f00 0000 0373 686f 7720 6461 .P+......show.da 0x0040: 7461 6261 7365 73 tabases 0x0000: 4500 00d3 7777 4000 4006 20ed ac1a 649b E...ww@.@.....d. 0x0010: 999c f76e 0cea c8cd 62c8 5cd1 9489 3a0f ...n....b.\...:. 0x0020: 8018 00db a286 0000 0101 080a 0051 8036 .............Q.6 0x0030: 32ec ab64 0100 0001 014b 0000 0203 6465 2..d.....K....de 0x0040: 6612 696e 666f 726d 6174 696f 6e5f 7363 f.information_sc 0x0050: 6865 6d61 0853 4348 454d 4154 4108 5343 hema.SCHEMATA.SC 0x0060: 4845 4d41 5441 0844 6174 6162 6173 650b HEMATA.Database. 0x0070: 5343 4845 4d41 5f4e 414d 450c 2100 c000 SCHEMA_NAME.!... 0x0080: 0000 fd01 0000 0000 1300 0003 1269 6e66 .............inf 0x0090: 6f72 6d61 7469 6f6e 5f73 6368 656d 6106 ormation_schema. 0x00a0: 0000 0405 6d79 7371 6c13 0000 0512 7065 ....mysql.....pe 0x00b0: 7266 6f72 6d61 6e63 655f 7363 6865 6d61 rformance_schema 0x00c0: 0400 0006 0373 7973 0700 0007 fe00 0022 .....sys......." 0x00d0: 0000 00 |
平文でリクエストとレスポンスが確認できました。
それでは暗号化して実施して見ましょう
クライアント側で先ほどのコマンドのオプションを除いて実行します。
その結果、下記のパケットが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
0x0000: 4500 0089 0000 4000 2706 b1ae 999c f76e E.....@.'......n 0x0010: ac1a 649b c8df 0cea 00fc 8af4 6507 23f0 ..d.........e.#. 0x0020: 8018 1000 aadf 0000 0101 080a 32f0 9aab ............2... 0x0030: 0055 7283 1703 0200 50a7 bf9c 09ee f1ce .Ur.....P....... 0x0040: d885 3d84 fc57 6a45 373b f9e9 9172 2315 ..=..WjE7;...r#. 0x0050: 7368 c9dd 0563 dd1a fb25 0d58 4508 8291 sh...c...%.XE... 0x0060: a387 9d3b c5b1 72c6 8869 7773 2fe4 8375 ...;..r..iws/..u 0x0070: 662d 8dfd 4689 d9af 1354 e341 df61 376d f-..F....T.A.a7m 0x0080: 1684 aec3 1233 08af 49 .....3..I 0x0000: 4500 00c9 6eaa 4000 4006 29c4 ac1a 649b E...n.@.@.)...d. 0x0010: 999c f76e 0cea c8df 6507 23f0 00fc 8b49 ...n....e.#....I 0x0020: 8018 00eb a27c 0000 0101 080a 0055 7295 .....|.......Ur. 0x0030: 32f0 9aab 1703 0200 907d ec6d dba1 d5a8 2........}.m.... 0x0040: 449b 4034 5fb1 c16e 33db 203f 80f9 1b4b D.@4_..n3..?...K 0x0050: ed27 fd41 9c87 a71f 01db 6807 8150 8d9b .'.A......h..P.. 0x0060: bf73 3ee2 9310 f3b4 1881 c135 f004 9bed .s>........5.... 0x0070: de5b 29a1 4bdb 2155 198b 4ae0 8626 edb9 .[).K.!U..J..&.. 0x0080: dbab a82b 8325 1b48 11b4 e3ec 2c3c 1f66 ...+.%.H....,<.f 0x0090: 4bed 5a5e 0e49 f66a ceb3 1857 4b57 0dcf K.Z^.I.j...WKW.. 0x00a0: 23c4 090b 60e7 ec35 64ca d661 9bd6 0dad #...`..5d..a.... 0x00b0: 4465 2cce 1eb2 6411 bd82 724e 4fdd e997 De,...d...rNO... 0x00c0: 3a49 f0ae d3b9 5d76 f2 :I....]v. |
暗号化されているので実際にどのような内容かはパケットからでは判断できませんので、
通信フローから実施したコマンドのパケットと判断しています。
SSLを使用したレプリケーションに関して
上記の手順で作成したMySQLサーバーでは下記のようにCHANGE MASTER TOステートメントで「MASTER_SSL=1」を設定すると、SSLを有効化出来ました。
1 2 3 4 5 6 7 |
CHANGE MASTER TO \ MASTER_HOST='ホストアドレス',\ MASTER_USER='ユーザー名,\ MASTER_PASSWORD='パスワード',\ MASTER_LOG_FILE='マスターのログファイル名,\ MASTER_SSL=1,\ MASTER_LOG_POS=マスターのログポジション; |
まとめ
以上で簡単にSSL/TLSの概要でした。
たとえプライベートなネットワークの中でも、何が起こるかわかりませんので出来る限りセキュリティを高めていく意識が大切ですね。