免責事項
この記事はTodd Farmer氏によるMySQL Server Blogの投稿「Identifying Insecure Connections」(2015/8/27)をユーザが翻訳したものであり、Oracle公式の文書ではありません。
MySQLサーバー5.7のキーとなるテーマはセキュリティーが大幅に改善されたことだ。MySQL 5.7の以前のリリースではTLSの証明書や鍵を自動で生成および検知するようになり、また、クライアント側でTLS接続が優先されるようになった。最近のMySQL 5.7.8のリリースはこれを基本としており、それに加えて「私のクライアント接続はどの程度安全か?」という疑問に簡単に答えられるようにする追加のモニタリングおよび監査機能を提供している。
接続の種別
MySQLクライアントの--protocolのコマンドライン引数には4つのプロトコルがあり、プラットフォーム毎にサポート状況が異なっている。
- TCP/IP (全プラットフォーム)
- ソケット (Unix/Linuxプラットフォームのみ)
- 共有メモリ (Windowsのみ)
- 名前付きパイプ (Windowsのみ)
MySQLサーバー内部では、SSL/TLSは5つめのオプション(これは --ssl* オプションで制御され、プロトコルとは少し独立している)として定義されている。 上記の中でソケットと共有メモリの接続はマシン間の接続をサポートせず(これらのプロトコルを利用する場合は同じマシン上にいる必要がある)、したがって「セキュアな」通信であるとみなすことができる。 一方で、名前付きパイプとTCP/IPは、ネットワークをまたいだ接続をサポートしており、通信が保護されていない。 したがって、「セキュアでない」通信とみなせる。SSL/TLSがこれらのプロトコル上で使われたとき唯一の例外となる。この2つのうち、MySQLではTCP/IPだけが現在はSSL/TLSをサポートしている。
従って次の接続が「セキュア」とみなせる。
- SSL/TLSと共に利用されるTCP/IPまたは名前付きパイプ
- ソケット
- 共有メモリ
ロギング
接続がどのように確立されたかを知ることは、かねてからの共通の監査要件であるため、接続種別の情報を一般クエリーログに加え、MySQL Enterpriseの監査ログにも追加した。一般クエリーログでは、接続(Connect)イベントのログエントリには次に示すように「... using [接続種別]」が加えられるよう拡張された。
2015-08-04T19:02:27.027365Z 6 Connect root@localhost on using Named Pipe
2015-08-04T19:02:35.208404Z 7 Connect root@localhost on using TCP/IP
2015-08-04T19:02:38.263292Z 8 Connect root@localhost on using SSL/TLS
この情報によってどの接続種別が使われどのアカウントで接続されたかが、誰にでも容易にわかるようになる。 一般クエリーログの内容を処理するツールは、接続(Connect)イベントのログエントリに追加されたテキスト情報を解釈させる為、更新が必要となるかもしれないことを述べておく。
同様に、監査ログのレコードは、接続イベントには新たに接続種別の情報を持ったCONNECTION_TYPEタグを含むようになる。 この情報は監査ログAPIにも追加され、このAPIを利用しているプラグインの開発者の方々はこの変更に追従したくなるだろう。
現在の接続の種別
接続種別のログ出力に加え、MySQL 5.7では現在の接続の接続種別を調べることができるようになった。また、CONNECTION_TYPE列がPERFORMANCE_SCHEMA.THREADSテーブルに追加された。
mysql> SELECT *
-> FROM performance_schema.threads
-> WHERE processlist_id = CONNECTION_ID()\G
*************************** 1. row ***************************
THREAD_ID: 35
NAME: thread/sql/one_connection
TYPE: FOREGROUND
PROCESSLIST_ID: 8
PROCESSLIST_USER: root
PROCESSLIST_HOST: localhost
PROCESSLIST_DB: NULL
PROCESSLIST_COMMAND: Query
PROCESSLIST_TIME: 0
PROCESSLIST_STATE: Sending data
PROCESSLIST_INFO: SELECT *
FROM performance_schema.threads
WHERE processlist_id = CONNECTION_ID()
PARENT_THREAD_ID: NULL
ROLE: NULL
INSTRUMENTED: YES
HISTORY: YES
CONNECTION_TYPE: SSL/TLS
1 row in set (0.00 sec)
PERFORMANCE_SCHEMA.THREADSテーブルにはクライアント接続に加え、内部スレッドの情報も含まれている為、CONNECTION_TYPEの値はNULLとなるかもしれない。
mysql> SELECT COUNT(*), connection_type
-> FROM performance_schema.threads
-> GROUP BY connection_type\G
*************************** 1. row ***************************
COUNT(*): 27
connection_type: NULL
*************************** 2. row ***************************
COUNT(*): 1
connection_type: SSL/TLS
2 rows in set (0.00 sec)
より深くみてみる
これまでに接続が安全な通信を利用しているかどうかに関する高位の概要を説明したが、考慮すべき追加の側面がある。 暗号化は全て同じように行われる訳ではないので、あるクライアント接続がどのTLS暗号化を利用しているかを調査する機能は有用である。そして魔法のパフォーマンススキーマを利用すると、それが可能となる。
MySQL 5.7以前は、その接続がどのTLS暗号化を利用しているかを調べることは可能であったが、他の接続においてどの暗号化が使われているかが確認できなかった。 この情報は\S (もしくはSTATUS)コマンドの一部である。
mysql> \s
--------------
bin\mysql Ver 14.14 Distrib 5.7.8-rc, for Win64 (x86_64)
Connection id: 8
Current database:
Current user: root@localhost
SSL: Cipher in use is DHE-RSA-AES256-SHA
...
セッションスコープのステータス変数でも出力される。
mysql> SHOW SESSION STATUS LIKE 'Ssl_cipher'\G
*************************** 1. row ***************************
Variable_name: Ssl_cipher
Value: DHE-RSA-AES256-SHA
1 row in set (0.00 sec)
MySQL 5.7では他の接続に関するセッションステータス変数を、いくつかの新しいPERFORMANCE_SCHEMAのテーブルを利用して出力できるようになった。
mysql> SELECT * FROM performance_schema.status_by_thread
-> WHERE variable_name = 'Ssl_cipher'\G
*************************** 1. row ***************************
THREAD_ID: 35
VARIABLE_NAME: Ssl_cipher
VARIABLE_VALUE: DHE-RSA-AES256-SHA
*************************** 2. row ***************************
THREAD_ID: 41
VARIABLE_NAME: Ssl_cipher
VARIABLE_VALUE: DHE-RSA-AES256-SHA
2 rows in set (0.00 sec)
mysql> SELECT
-> processlist_id,
-> processlist_user,
-> processlist_host,
-> connection_type,
-> variable_value AS cipher
-> FROM
-> performance_schema.threads t
-> JOIN
-> performance_schema.status_by_thread sbt
-> ON (t.thread_id = sbt.thread_id AND sbt.variable_name = 'Ssl_cipher')
-> WHERE connection_type IS NOT NULL\G
*************************** 1. row ***************************
processlist_id: 8
processlist_user: root
processlist_host: localhost
connection_type: SSL/TLS
cipher: DHE-RSA-AES256-SHA
*************************** 2. row ***************************
processlist_id: 15
processlist_user: root
processlist_host: localhost
connection_type: TCP/IP
cipher:
2 rows in set (0.00 sec)
それぞれの接続の現在のTLS暗号化手法の情報に加え、DBAは暗号化手法の候補のリストを調べることができる。これによって、サーバー側である暗号化を制限(--ssl-cipherサーバーオプションを変更することにより)した場合にどのクライアントが影響を受けるかを評価することができる。このケースではSsl_cipher_listセッションステータス変数をみればよいだろう。
mysql> SELECT
-> processlist_id,
-> processlist_user,
-> processlist_host,
-> connection_type,
-> variable_value AS cipher
-> FROM
-> performance_schema.threads t
-> JOIN
-> performance_schema.status_by_thread sbt
-> ON (t.thread_id = sbt.thread_id AND sbt.variable_name = 'Ssl_cipher_list'
)
-> WHERE connection_type IS NOT NULL\G
*************************** 1. row ***************************
processlist_id: 8
processlist_user: root
processlist_host: localhost
connection_type: SSL/TLS
cipher: DHE-RSA-AES256-SHA:AES256-SHA:DHE-RSA-AES128-SHA:AES128-SHA:AE
S256-RMD:AES128-RMD:DES-CBC3-RMD:DHE-RSA-AES256-RMD:DHE-RSA-AES128-RMD:DHE-RSA-D
ES-CBC3-RMD:RC4-SHA:RC4-MD5:DES-CBC3-SHA:DES-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-RS
A-DES-CBC-SHA
*************************** 2. row ***************************
processlist_id: 15
processlist_user: root
processlist_host: localhost
connection_type: TCP/IP
cipher:
2 rows in set (0.00 sec)
まとめ
MySQLサーバー 5.7で追加されたクライアントで利用されている接続種別を調べる機能は、MySQLのセキュリティーを評価しモニタリングしようと考えているDBAの人々にとても役に立つだろうし、これはMySQL 5.7で拡張されたパフォーマンススキーマの実際の応用例の1つである。
これらの機能にコメントや質問があれば、教えて欲しい。いつものように、MySQLを使ってくれてありがとう!