MariaDBでSSL通信
Webを筆頭にはネットワーク接続はSSLが主流になってきました。。それに伴ってMariaDBサーバーへのコネクションもSSL化したいと思い挑戦してみました。
OpenSSL
まずはOpenSSLで証明書を発行しなければいけません。OpenSSLについては「OpenSSLで認証局を作って証明書を発行する」の回で詳しく説明していますが、今回は公式ページの「TLS による MariaDB Server との通信暗号化」にあるスクリプトを利用して作成しました。これはLinux用のスクリプトなので実行する際はLinux環境で実行してください。
このスクリプトは必ずしも使わなくてはいけないというものではありません。利用できるCAの証明書と、そのCAが署名したサーバ用の証明書、サーバーの秘密鍵があればいいです。
makeCert.sh
#!/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 …1
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 …2
issuer | openssl req -new -x509 -nodes -days 365 -key ca-key.pem -out ca-cert.pem …3
server | openssl req -newkey rsa:2048 -days 365 -nodes -keyout server-key.pem -out server-req.pem …4
openssl rsa -in server-key.pem -out server-key.pem …5
openssl x509 -req -in server-req.pem -days 365 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem …6
下線部の説明をしていきます。
1.の箇所はMariaDBが稼働しているサーバーのFDQN(ドメイン&ホスト名)か、IPアドレスに変更する必要があります。
2.の箇所ではCA用のキーを発行しています。
3.の箇所ではCA用の自己署名をしています。
- openssl reqは、証明書要求と証明書発行のためのユーティリティです。
- -newは新規に証明書発行要求します。
- -x509は証明書要求を発行するかわりに自己署名をします。
- -nodesは暗号化をしないオプションです。
- -keyには前段階で出力したCAのキー
- -outには出力する証明書ファイルを指定しています。
4.の箇所ではMariaDBサーバー用の秘密鍵を作成するのと同時に署名要求を作成しています。
- -newkeyは新規に秘密鍵を作成して証明書署名要求をします。
この時引数にrsa:2048とすることで、rsa2048bitを指定しています。
- -keyoutとすることでその引数に指定したファイル名で秘密鍵を出力します。
- -outには出力する証明書署名要求ファイル名をを指定します。
5.の箇所では先にrsa:2048と指定して作成したキーをRSAキーに変換しています。一見何もしていないようにも見えますが、中身のファイルのヘッダが「PRIVATE KEY」だったものが「RSA PRIVATE KEY」に変わりました。Windows環境では変換しないでもつかえましたが、Debian環境ではこの変換を行わないとSSL通信ができませんでした。
6.の箇所ではサーバーの証明書要求に対して実際の署名をしています。
- openssql x509は署名と確認のためのユーティリティです。
- -reqで証明書署名要求を処理します。
- -inで証明書署名要求ファイルを指定します。
- -CAで署名するCAの証明書を指定します。
- -CAKeyでCAの秘密鍵を指定します。
- -set_serial 01は署名用の管理インデックスを指定しています。
- -outで署名済みの出力する証明書ファイルを指定します。
参考サイト上ではサーバーの署名の後に、クライアント用の証明書もサーバーと同じ手順で署名していますが、この記事では利用しませんので割愛します。
Windows10で稼働しているMariaDBサーバーにSSLを設定してみる
Windows10にインストールしたMariaDBサーバーにSSLを設定してみます。
設定ファイルはC:¥Program Files¥MariaDB 10.5¥data¥my.iniにあります。
my.ini
[mysqld]
datadir=C:/Program Files/MariaDB 10.5/data
port=3306
innodb_buffer_pool_size=501M
ssl-ca = C:/Program Files/MariaDB 10.5/data/ca-cert.pem
ssl-key = C:/Program Files/MariaDB 10.5/data/server-key.pem
ssl-cert = C:/Program Files/MariaDB 10.5/data/server-cert.pem
[client]
port=3306
plugin-dir=C:/Program Files/MariaDB 10.5/lib/plugin
デフォルトの設定に下線の3行を追加した形です。CAの証明書(ca-cert.pem)、サーバーの秘密鍵(server-key.pem)、サーバーの証明書(server-cert.pem)の絶対パスを記述します。ここに記述した場所に、先ほど生成したそれぞれのファイルを置きます。ここではC:¥Program Files¥MariaDB 10.5¥dataに配置しました。
設定の記述とファイルのコピーをしたら、MariaDBのサービスを再起動させるか、OSを再起動させます。
コンソールから次のようにしてMariaDBに接続します。
> mysql -u user -p -h 192.168.1.1 --ssl
-hオプションはサーバーのIPアドレスを指定するものです。--sslオプションがSSL通信を指定します。上記の設定の際SSL通信をするだけでサーバーの証明書はチェックされていませんので注意してください。
mariaDB接続中にSSL通信ができているかどうかは、「show status like 'Ssl_cipher';」コマンドで確認するそうです。コマンドを実行した際Valueに何か文字列が入っていればSSL通信をしています。こちらの方法はハックノート:「MySQLにsslで接続しているか確認する方法」を参考にさせていただきました。ありがとうございました。
MariaDB [(none)]> show status like 'Ssl_cipher';
+---------------+------------+
| Variable_name | Value |
+---------------+------------+
| Ssl_cipher | AES256-SHA |
+---------------+------------+
1 row in set (0.002 sec)
SSL通信ができるようになったら今度は、サーバーの証明書のチェックをしてみます。証明書をチェックする場合は--ssl-caでCAの証明書を設定した後、--ssl-verify-server-certオプションを付与します。--ssl-caオプションは--sslオプションを付与したとみなしますので、先にあった--sslオプションは不要です。
--ssl-caに指定するファイルはローカルにあるCA証明書です。MariaDBサーバーに配置してあるものをローカルにコピーしてください。
他、TLSを接続したい(--tls-version=TLSv1.3)等、接続時のコマンドはmysql Command-line Clientのページに載っていますので確認してみてください。
証明書のチェックに失敗すると接続はキャンセルされます。基本的に証明書のcommon nameと同じ値を-hの引数に渡さなければいけません。例えば証明書のcommon nameを「localhost」とした時は-hの引数として「127.0.0.1」を渡して接続しようとするとエラーになります。
> mysql -u user -p -h 192.168.1.1 --ssl-ca="C:/Program Files/MariaDB 10.5/data/ca-cert.pem" --ssl-verify-server-cert
問題なければ通常通りログインされます。エラーの際は次のようなメッセージが出ます。上段のエラーはCommon Nameの相違、下段のエラーはサーバー側のキーファイルと証明書ファイルのセットが不正な場合に出たものです。
ERROR 2026 (HY000): SSL connection error: Server certificate validation failed. The certificate's CN name does not match the passed value. Error 0x800B010F(CERT_E_CN_NO_MATCH)
ERROR 2026 (HY000): SSL connection error: Server certificate validation failed. The signature of the certificate cannot be verified. Error 0x80096004(TRUST_E_CERT_SIGNATURE)
単にサーバーにSSLの設定をしただけの場合、SSLでも非SSLでも接続が可能です。ユーザーにSSLを強制させるにはGRANT時にREQUIRE SSLを付与します。
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO username@'%' IDENTIFIED BY 'password' REQUIRE SSL;
Debian(buster)の場合
DebianでMariaDBの設定としてSSLを指定するには[mysqld]のエントリーに先のWindowsの時と同様の記述をすれば設定可能です。設定ファイルは/etc/mysql/mariadb.conf.d/50-server.cnfになります。
おそらくデフォルトの設定ファイルの[mysqld]セクションの中頃にssl-caから始まる項目がコメントアウトされて入っていると思います。
Debianでは権限があるので、mysqlユーザーが証明書ファイルを読めるように気をつけてください。
50-server.cnf
[mysqld]
...
ssl-ca = /etc/mysql/ca-cert.pem
ssl-key = /etc/mysql/server-key.pem
ssl-cert = /etc/mysql/server-cert.pem
...
また、MariaDBのCommunityServer版ではバージョン10.5から「require_secure_transport」のシステム変数が利用できるようになり、この値をONとしておくとすべての非暗号化通信を拒否できるようになります。
50-server.cnf
[mysqld] ... require_secure_transport=on ...