TLS による MariaDB Server との通信暗号化

ほぼ毎日のように大規模な情報漏洩の報道を目にする機会も多い昨今ですが,Googleの検索エンジンにおいて https:// で始まる,SSLで暗号化されたwebページを優先してインデックスしていることもあり,今日ほとんどのwebページはSSLでブラウザとwebサーバ間の通信が暗号化されています。

Webアプリケーションサーバとデータベースサーバ間,もしくは MaxScale などのデータベースproxyとの通信はプライベートネットワーク内で行われる場合が多く,通信は暗号化されていない場合も多いですが,情報漏洩は社内から発生することも多く,理想的にはすべてのレベルにおいてデータを暗号化することが望ましいと考えられます。

本投稿では MariaDB Server 10.0.15 からサポートされているTLSによる通信暗号化に関して解説致します。

テスト実行環境

今回は以下の実行環境でテストを行います。

  • CentOS 7.6.1810
  • MariaDB 10.3.11 GA
  • OpenSSL 1.0.2k

基本的に以下の作業は root ユーザで実施致します。

TLS証明書/秘密鍵の作成

OpenSSL を用いたTLS秘密鍵,証明書の作成手順は以下のMariaDB Knowledge Baseに解説されています。

Certificate Creation with OpenSSL

今回はあくまでテストのため,以下のbashスクリプトでダミーのCA情報,組織,サーバ/クライアント情報で自己署名証明書を作成します。なお,production環境では適切な情報を入力してください。

#!/bin/sh

issuer() {
        echo JP
        echo Tokyo
        echo Chiyoda-ku
        echo --
        echo self CA
        echo --
        echo ""
}
server() {
        echo JP
        echo Tokyo
        echo Shinjuku-ku
        echo Your Company
        echo ""
        echo mdb103.yourcompany.com
        echo foo@yourcompany.com
        echo ""
        echo ""
}
client() {
        echo JP
        echo Tokyo
        echo Shinjuku-ku
        echo Client
        echo ""
        echo ""
        echo bar@yourcompany.com
        echo ""
        echo ""
}

cd /etc/pki/tls/certs
openssl genrsa 2048 > ca-key.pem
issuer | openssl req -new -x509 -nodes -days 365 -key ca-key.pem \
           -out ca-cert.pem

server | openssl req -newkey rsa:2048 -days 365 -nodes \
           -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 365 -CA ca-cert.pem \
  -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

client | openssl req -newkey rsa:2048 -days 365 -nodes \
            -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 365 -CA ca-cert.pem \
  -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

以下のコマンドで,サーバ証明書とクライアント証明書をチェックします。

# openssl verify -CAfile ca-cert.pem server-cert.pem
server-cert.pem: OK
# openssl verify -CAfile ca-cert.pem client-cert.pem
client-cert.pem: OK

上記のメッセージのように,双方OKとなっていれば問題ありません。

MariaDB Serverの設定

TLSを有効にしていない状態で,mysql(MariaDB monitor)で以下のSQLを実行しますと,以下のような出力が得られます。

MariaDB [(none)]> SHOW VARIABLES LIKE 'have_ssl';
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| have_ssl      | DISABLED |
+---------------+----------+

/etc/my.cnf.d/tls.cnf に以下の設定を行い,mariadb service を再起動(sytsemctl restart mariadb)します。

[mariadb]
log_error
ssl-ca   = /etc/pki/tls/certs/ca-cert.pem
ssl-key  = /etc/pki/tls/certs/server-key.pem
ssl-cert = /etc/pki/tls/certs/server-cert.pem

[mysql]
ssl-ca   = /etc/pki/tls/certs/ca-cert.pem
ssl-key  = /etc/pki/tls/certs/client-key.pem
ssl-cert = /etc/pki/tls/certs/client-cert.pem

ここで,

ssl-ca: CA(Certificate Authority, 認証局)証明書
ssl-key: SSL証明書の秘密鍵
ssl-cert: SSL証明書

となります。

エラーログ(/var/lib/mysql/hostname.err)を確認しますと,以下のエラーが発生しています。

SSL error: Unable to get private key from '/etc/pki/tls/certs/server-key.pem'
2018-12-16 16:55:24 0 [Warning] Failed to setup SSL
2018-12-16 16:55:24 0 [Warning] SSL error: Unable to get private key
2018-12-16 16:55:24 0 [Warning] SSL error: error:0200100D:system library:fopen:Permission denied
2018-12-16 16:55:24 0 [Warning] SSL error: error:20074002:BIO routines:FILE_CTRL:system lib
2018-12-16 16:55:24 0 [Warning] SSL error: error:140B0002:SSL routines:SSL_CTX_use_PrivateKey_file:system lib

秘密鍵のowner/permissionを確認しますと,owner が root, mode が 600 ですので,mysqld を実行している mysql ユーザではread権限がありません。

# ls -l /etc/pki/tls/certs/server-key.pem
-rw------- 1 root root 3258 Dec 16 13:42 /etc/pki/tls/certs/server-key.pem

*.pem ファイルの owner を mysql にするか,modeを適宜変更します。

# cd /etc/pki/tls/certs
# chown mysql *.pem
# chmod go-rwx *-key.pem

mariadb service を再起動します。

# systemctl restart mariadb

エラーログに先ほどのようなエラーがないことが確認できましたら,mysql(MariaDB monitor)で再度 SSL/TLS 関連の MariaDB 変数を確認しますと,以下のようになります。

MariaDB [(none)]> SHOW VARIABLES LIKE '%ssl%';
+---------------------+------------------------------------+
| Variable_name       | Value                              |
+---------------------+------------------------------------+
| have_openssl        | YES                                |
| have_ssl            | YES                                |
| ssl_ca              | /etc/pki/tls/certs/ca-cert.pem     |
| ssl_capath          |                                    |
| ssl_cert            | /etc/pki/tls/certs/server-cert.pem |
| ssl_cipher          |                                    |
| ssl_crl             |                                    |
| ssl_crlpath         |                                    |
| ssl_key             | /etc/pki/tls/certs/server-key.pem  |
| version_ssl_library | OpenSSL 1.0.1e-fips 11 Feb 2013    |
+---------------------+------------------------------------+

DBeaverを用いリモートホストから接続テスト

次にリモートホストからGUIクライアントのDBeaverとパケットキャプチャツールのWiresharkを用いて通信が暗号化されているか確認してみました。

以下の動画にテストの様子をキャプチャしてあります。

https://mariadb-jp.wistia.com/medias/qjcpgdw54c

SSL接続では通信が暗号化されていることが確認できます。

TLS接続必須アカウント設定

ユーザ作成,もしくは変更時に require SSL オプションを付与することにより,特定のユーザにTLS接続を要求することが可能です。

例:

GRANT ALL ON *.* TO ssl_user@'%' IDENTIFIED BY 'password' REQUIRE SSL;

まとめ

MariaDB Server 10.0.15 以降実装されているTLSによる通信暗号化に関して解説いたしました。MariaDB Server 上に保存されているデータの暗号化(Data-at-Rest Encryption)に関しましては,こちらの過去記事に解説されておりますのであわせてご覧いただけますと幸いです。