Last Updated on 2021年7月4日 by かんりにん
リモートホストのMySQLサーバーへアクセスする際に、クライアント – サーバー間の通信を暗号化する方法をかるく検証。
(MySQLのDBスキーマやテーブルの暗号化ではない)
方法としてはベタな感じだけど、手っ取り早く以下の2パターンで。
- sshでトンネリングした状態でmysqlへ接続
- SSLでmysqlへのセッションから暗号化する
【1.ssh】
sshでのポートフォワーディングによるmysqlのコネクション暗号化。
-参考:お世話になっております!
OpenSSH FAQ 2.11 – How do I use port forwarding?
ポイント
- おもにssh接続の設定作業なるので、接続先のDBサーバー側は原則として設定変更しなくてもOK
- ローカル側でトンネリング用のsshを立ち上げることになるので、バックグラウンドで実行する
オプション(“-f”)をつけること。
テストで使用した設定
接続元ホスト
IP | 192.168.254.32 |
sshポート | 22 |
DBサーバーへの接続用sshポート | 23306(→DBサーバーの3306番へアクセスする) |
接続先DBサーバー
IP | 192.168.254.64 |
ログインユーザー | user |
sshポート | 22 |
mysqlポート | 3306 |
設定
1)トンネリング設定
接続元ホスト側で接続先DBサーバーのポートフォワーディングを設定
$ ssh -f -N -L 23306:localhost:3306 user@192.168.254.64 -p 22
[オプション解説]
-f バックグラウンドで実行 -N リモート・ホストでのコマンドを許可しない。※ポート転送をするときに指定すること。 -L ローカル側のポート転送機能を利用する
[ポート解説]
ローカルホスト(接続元)の23306へアクセス→DBサーバーの3306番へアクセス
トンネリング先となるDBサーバーのsshのポートとして、22番を指定
実行後、プロセスとポートを確認。
$ ps -aef | grep "ssh -f" | grep -v grep user 8650 1 0 13:14 ? 00:00:00 ssh -f -N -C -L 23306:localhost:3306 user@192.168.254.64 -p 22
$ netstat -ln | grep 23306 tcp 0 0 127.0.0.1:23306 0.0.0.0:* LISTEN tcp 0 0 ::1:23306 :::* LISTEN
2)接続確認
ローカルホストの23306番を指定し、DBサーバーへ接続。
$ mysql -u testschema_user -p testschema -h 127.0.0.1 --port=23306 Enter password: mysql> show tables; +----------------------+ | Tables_in_testschema | +----------------------+ | tbl_testschema | +----------------------+ 1 row in set (0.03 sec)
→接続成功。
【2.ssl】
sslの鍵交換による暗号化をささっと。
-参考:お世話になっております!
MySQL 5.1 リファレンスマニュアル 4.8.7.2. SSL接続
suz-lab – blog: MySQLにSSLで接続
ポイント
SSLの認証が発生するので、クライアント側に秘密鍵、DBサーバー側に証明書が必要。またピアノード間で使用するCAが必要。
テストで使用した設定
CA | ca-cert.pem |
秘密鍵 | server-key.pem |
証明書 | server-cert.pem |
設定
1)mysqlの状態を確認
mysql> SHOW VARIABLES LIKE '%ssl%'; +---------------+----------+ | Variable_name | Value | +---------------+----------+ | have_openssl | DISABLED | ←ここ | have_ssl | DISABLED | ←ここ | ssl_ca | | | ssl_capath | | | ssl_cert | | | ssl_cipher | | | ssl_key | | +---------------+----------+ 7 rows in set (0.00 sec)
SSL接続が有効になっていないことを確認。
2)SSL環境設定
SSL証明書関連の保管先ディレクトリを作成。
mysql.dというディレクトリを作成。
# mkdir /etc/mysql.d
CA のキーを生成
# openssl req -new -x509 -nodes -days 365 -key ca-key.pem -out ca-cert.pem --- Country Name (2 letter code) [XX]:JP State or Province Name (full name) []:Tokyo Locality Name (eg, city) [Default City]:dokokano-Ku Organization Name (eg, company) [Default Company Ltd]:hogehoge Organizational Unit Name (eg, section) []:system Common Name (eg, your name or your server's hostname) []:localhost.localdomain Email Address []:webmaster@example.com
MySQL サーバーの秘密鍵と CSR の作成
# openssl req -newkey rsa:2048 -days 365 -nodes -keyout server-key.pem -out server-req.pem ----- Country Name (2 letter code) [XX]:JP State or Province Name (full name) []:Tokyo Locality Name (eg, city) [Default City]:dokokano-Ku Organization Name (eg, company) [Default Company Ltd]:hogehoge Organizational Unit Name (eg, section) []:system Common Name (eg, your name or your server's hostname) []:localhost.localdomain Email Address []:webmaster@example.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
MySQL サーバーの証明書作成
# openssl x509 -req -in server-req.pem -days 365 -CA ca-cert.pem -CAkey ca-key.pem -out server-cert.pem -set_serial 01 Signature ok subject=/C=JP/ST=Tokyo/L=dokokano-Ku/O=hogehoge/OU=system/CN=localhost.localdomain/emailAddress=webmaster@example.com Getting CA Private Key
my.cnf へ設定追加
# cp -p my.cnf my.cnf.20130927 # vi my.cnf
設定内容
[mysqld] # SSL configuration ssl-ca=/etc/mysql.d/ca-cert.pem ssl-cert=/etc/mysql.d/server-cert.pem ssl-key=/etc/mysql.d/server-key.pem
MySQL の再起動を行う
# /etc/init.d/mysqld restart
SSL設定の適用を確認
mysql> SHOW VARIABLES LIKE '%ssl%'; +---------------+------------------------------+ | Variable_name | Value | +---------------+------------------------------+ | have_openssl | YES | | have_ssl | YES | | ssl_ca | /etc/mysql.d/ca-cert.pem | | ssl_capath | | | ssl_cert | /etc/mysql.d/server-cert.pem | | ssl_cipher | | | ssl_key | /etc/mysql.d/server-key.pem | +---------------+------------------------------+ 7 rows in set (0.01 sec)
3)クライアント側からの設定(ローカル)
GRANT実行時にオプション”REQUIRE SSL”をつける。
mysql> GRANT ALL PRIVILEGES ON testschema.* TO testuser@localhost IDENTIFIED BY 'PASSWORD' REQUIRE SSL; mysql> flush privileges;
接続テスト
# mysql -h localhost -u testuser --ssl-ca=/etc/mysql.d/server-cert.pem -p testschema Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. mysql>
→ログインは成功。
SSLの接続状態を確認
mysql> show status like'Ssl_cipher'; +---------------+--------------------+ | Variable_name | Value | +---------------+--------------------+ | Ssl_cipher | DHE-RSA-AES256-SHA | +---------------+--------------------+ 1 row in set (0.00 sec)
4)クライアント側からの設定(リモート)
サーバー証明書をリモートホストに転送してから、同様に接続を行うこと。
DBサーバー側にリモートホスト(クライアント)からの接続用アカウントを作成
クライアントのIPは192.168.254.32。
mysql> GRANT ALL PRIVILEGES ON *.* TO testuser@192.168.254.32 IDENTIFIED BY 'PASSWORD' REQUIRE SSL; mysql> flush privileges;
クライアント側に証明書を作成
※SCPで転送してもOK。
$ mkdir mysql.d $ cd mysql.d/ $ touch server-cert.pem $ vi server-cert.pem
接続テスト
$ mysql -h 192.168.254.64 -u testuser --ssl-ca=server-cert.pem -p testschema Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. mysql>
→ログインは成功。
SSLの接続状態を確認
mysql> show status like'Ssl_cipher'; +---------------+--------------------+ | Variable_name | Value | +---------------+--------------------+ | Ssl_cipher | DHE-RSA-AES256-SHA | +---------------+--------------------+ 1 row in set (0.03 sec)
あとはローカル、リモートでそれぞれ暗号化通信を確認できればOK。
今回はこんな感じで。