TCP Proxyを書いてMySQLの通信を覗いてみる

"TCP Proxyを書いてPostgreSQLの通信を覗いてみる - Copy/Cut/Paste/Hatena" の続編です。

MySQLの通信を覗いてみる

また簡単なクエリだけを対象にします(プリペアードステートメントなどは含みません)。

MySQLもしっかりとしたドキュメントがありクエリのプロトコルの説明もありました。

MySQL :: MySQL Internals Manual :: 14.6.4 COM_QUERY

しかし、とみたまさひろさん の資料のほうが断然わかりやすかったです。

slide.rabbit-shocker.org

というわけで今回も tcprxy に実装を追加していきます。

mysqlコマンドでクエリを実行してみます。

my:root@localhost:3306/testdb=> SELECT COUNT(*) FROM information_schema.tables;
  COUNT(*)
+----------+
       305
(1 rows)

まずは tcprxy -d hex で覗きます。

00000000  30 00 00 00 03 53 45 4c  45 43 54 20 43 4f 55 4e  |0....SELECT COUN|
00000010  54 28 2a 29 20 46 52 4f  4d 20 69 6e 66 6f 72 6d  |T(*) FROM inform|
00000020  61 74 69 6f 6e 5f 73 63  68 65 6d 61 2e 74 61 62  |ation_schema.tab|
00000030  6c 65 73 3b                                       |les;|
00000000  01 00 00 01 01 1e 00 00  02 03 64 65 66 00 00 00  |..........def...|
00000010  08 43 4f 55 4e 54 28 2a  29 00 0c 3f 00 15 00 00  |.COUNT(*)..?....|
00000020  00 08 81 00 00 00 00 05  00 00 03 fe 00 00 22 00  |..............".|
00000030  04 00 00 04 03 33 30 35  05 00 00 05 fe 00 00 22  |.....305......."|
00000040  00                                                |.|

クエリのデータは、1-3バイト目がデータ長、4バイト目がシーケンス番号、5バイト目からデータで、その先頭バイトが 0x03 になっているので、そのメッセージだけ受け取ってクエリの文字列だけ取得します

-d オプションに、今回作成したmysql を指定して 33306 ポートで待ち受けます。

$ tcprxy -l localhost:33306 -r localhost:3306 -d mysql

適当なクエリを実行。

my:root@localhost:33306/testdb=> SELECT COUNT(*) FROM information_schema.tables;
  COUNT(*)
+----------+
       305
(1 rows)

my:root@localhost:3306/testdb=> SELECT COUNT(*) FROM information_schema.columns;
  COUNT(*)
+----------+
      3269
(1 rows)

出力は以下。

$ tcprxy -l localhost:33306 -r localhost:3306 -d mysql
SELECT COUNT(*) FROM information_schema.tables;
SELECT COUNT(*) FROM information_schema.columns;

MySQLでもクエリ取得ができました。

まとめ

今度はプリペアードステートメントなども取得して、組み立ててみたいです。