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?
http://www.openssh.com/faq.html#2.11
- 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: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 13 Server version: 5.1.69-log Source distribution Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 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接続
http://dev.mysql.com/doc/refman/5.1/ja/secure-using-ssl.html - suz-lab – blog: MySQLにSSLで接続
http://blog.suz-lab.com/2011/08/mysqlssl.html
- MySQL 5.1 リファレンスマニュアル 4.8.7.2. 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)
mysql>
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) mysql>
あとはローカル、リモートでそれぞれ暗号化通信を確認できればOK。
今回はこんな感じで。