MySQL 5.7でSSL接続が有効になる条件
MySQL 5.7から、SSL接続が有効になっている場合、クライアントからSSL接続を行うと明示しなくても自動でSSL接続になる。
MySQLサーバがSSL接続が有効になるのは二通り。
- my.cnfでSSL証明書読み込んだ場合
- data directoryに規定の名前の有効なSSL証明書がある場合
my.cnfによる設定
https://dev.mysql.com/doc/refman/5.7/en/using-encrypted-connections.htmlによると、以下に引用する通り3つのオプションがあり、my.cnfでも[mysqld]
セクションにssl-ca
, ssl-cert
, ssl-key
を設定できる。
On the server side, the --ssl option specifies that the server permits but does not require encrypted connections. This option is enabled by default.
These options on the server side identify the certificate and key files the server uses when permitting clients to establish encrypted connections:
- --ssl-ca: The path name of the Certificate Authority (CA) certificate file. (--ssl-capath is similar but specifies the path name of a directory of CA certificate files.)
- --ssl-cert: The path name of the server public key certificate file. This can be sent to the client and authenticated against the CA certificate that it has.
- --ssl-key: The path name of the server private key file.
自動読み込み
data directoryに規定の名前の有効なSSL証明書がある場合は、MySQLが起動時に自動で読み込んでくれる。
If the server discovers valid certificate and key files named ca.pem, server-cert.pem, and server-key.pem in the data directory, it enables support for encrypted connections by clients.
ca.pem
, server-cert.pem
, server-key.pem
はmysql_ssl_rsa_setup
というツールが自動で生成してくれる。
https://dev.mysql.com/doc/refman/5.7/en/mysql-ssl-rsa-setup.html
SSL接続が有効かどうかの確認
SSLが有効になっているかどうかはshow variables
で確認できる。
mysql> show variables like '%ssl%';
+---------------+---------------------------+
| Variable_name | Value |
+---------------+---------------------------+
| have_openssl | YES |
| have_ssl | YES |
略
またstatus
で現在の自身の接続がSSLになっているかが確認できる。
$ read -sp password? MYSQL_PWD
# unix domain socket経由だと当然SSLは使えない
MYSQL_PWD=$MYSQL_PWD mysql -uroot -e 'status' | grep SSL
SSL: Not in use
# TCP経由だとSSLが使える
$ MYSQL_PWD=$MYSQL_PWD mysql -uroot --protocol tcp -e 'status' | grep SSL
SSL: Cipher in use is DHE-RSA-AES256-SHA
コネクションプーリングを利用しない場合はMySQLのSSL無効化したほうがいい
本題に入る。
SSL接続は接続コストが高く、CPU使用率が簡単に上がってしまう。
コネクションプーリングをしている場合、都度接続をするわけではないのでSSL接続時のCPU負荷は無視できる。SQL実行時にはSSLによる暗号化が行われるが、接続開始時ほどCPU負荷にはつながらない。
従来、PostgreSQLやOracleと違ってMySQLは接続コストが低いためフェイルオーバー時などに考慮すべき点が増えるくらいならコネクションプーリングを使用しないでいいという考えもあったので、その考えのままSSL接続してしまうと、DBサーバと接続元のAPサーバともにCPU負荷が上がってしまう。
CPU負荷の上昇をどうやって確認したか
SSL接続でどれくらいCPU負荷が上がるかについて一例をあげると、Fluentd(td-agent)でMySQLに大量のアプリケーションログを送ったとき、DBサーバのCPU負荷は4倍になっていた。 これを確認した方法を記載する。
perf record
でFluentdの負荷状況を取得した。
perf record -g -p td-agentのPID sleep 120
perf report -g -G --stdio
で情報を表示する。そうすると負荷の上位にMySQLへのコネクションに関する処理があることがわかった。
5.87% 0.00% thread.rb:70 mysql2.so [.] nogvl_connect
|
---nogvl_connect
|
--5.84%--mysql_real_connect
|
--5.67%--sslconnect
|
--5.05%--yaSSL_connect
|
--4.68%--yaSSL::sendClientKeyExchange
|
--4.54%--yaSSL::ClientKeyExchange::build
yaSSL::ClientDiffieHellmanPublic::build
|
|--2.26%--TaoCrypt::DH::GeneratePublic
| |
| --2.26%--TaoCrypt::a_exp_b_mod_c
| |
| --2.26%--TaoCrypt::AbstractRing::Exponentiate
| TaoCrypt::ModularArithmetic::SimultaneousExponentiate
| |
| --2.24%--TaoCrypt::AbstractGroup::SimultaneousMultiply
| |
| |--1.69%--TaoCrypt::MontgomeryRepresentation::Square
| | |
| | |--1.06%--TaoCrypt::MontgomeryReduce
| | | |
| | | --0.53%--TaoCrypt::RecursiveMultiplyTop
| | |
| | --0.63%--TaoCrypt::RecursiveSquare
| |
| --0.52%--TaoCrypt::AbstractRing::MultiplicativeGroupT::Accumulate
| TaoCrypt::MontgomeryRepresentation::Multiply
|
--2.25%--TaoCrypt::DH::Agree
|
--2.24%--TaoCrypt::a_exp_b_mod_c
TaoCrypt::AbstractRing::Exponentiate
|
--2.24%--TaoCrypt::ModularArithmetic::SimultaneousExponentiate
|
--2.21%--TaoCrypt::AbstractGroup::SimultaneousMultiply
|
|--1.66%--TaoCrypt::MontgomeryRepresentation::Square
| |
| |--1.08%--TaoCrypt::MontgomeryReduce
| | |
| | --0.52%--TaoCrypt::RecursiveMultiplyTop
| |
| --0.57%--TaoCrypt::RecursiveSquare
|
--0.51%--TaoCrypt::AbstractRing::MultiplicativeGroupT::Accumulate
|
--0.50%--TaoCrypt::MontgomeryRepresentation::Multiply
td-agent.conf
でSSL接続に関する設定を一つもしていないのでSSL接続をしている認識がなかったが、sslconnect
という文字列が見えたため、MySQL 5.7以降の「SSL接続が有効になっている場合、クライアントからSSL接続を行うと明示しなくても自動でSSL接続になる」という仕様に気付いた。
MySQLのSSLを無効にした後、再度Fluentdに対してperf record
, perf report
を実行したところ、SSL接続に関する処理はなくなり、Load AverageやMySQLのqps, tpsにも改善が見られた。