Mysql 通信协议抓包分析

mysql在传输层使用的TCP协议。一个TCP payload可能有多个mysql packet。如下图所示。

TCP head TCP payload
(mysql packet1, mysql packet2,mysql packet 3...)

下面通过抓包分析其结构。

执行如下SQL语句,并抓包:

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)

client 请求包

PACKET: 75 bytes, wire length 75 cap length 75 @ 2018-10-10 16:17:44.545962 +0800 CST
- Layer 1 (04 bytes) = Loopback {Contents=[2, 0, 0, 0] Payload=[..71..] Family=IPv4}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..51..] Version=4 IHL=5 TOS=0 Length=71 Id=0 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=0 SrcIP=172.24.232.150 DstIP=172.24.232.150 Options=[] Padding=[]}
- Layer 3 (32 bytes) = TCP {Contents=[..32..] Payload=[..19..] SrcPort=51905 DstPort=3306(mysql) Seq=1194291158 Ack=850183053 DataOffset=8 FIN=false SYN=false RST=false PSH=true ACK=true URG=false ECE=false CWR=false NS=false Window=9352 Checksum=10648 Urgent=0 Options=[TCPOption(NOP:), TCPOption(NOP:), TCPOption(Timestamps:462864359/462163474 0x1b96bfe71b8c0e12)] Padding=[]}
- Layer 4 (19 bytes) = Payload 19 byte(s) tcp:&{{[202 193 12 234 71 47 111 214 50 172 195 141 128 24 36 136 41 152 0 0 1 1 8 10 27 150 191 231 27 140 14 18] [15 0 0 0 3 115 104 111 119 32 100 97 116 97 98 97 115 101 115]} 51905 3306(mysql) 1194291158 850183053 8 false false false true true false false false false 9352 10648 0 [202 193] [12 234] [TCPOption(NOP:) TCPOption(NOP:) TCPOption(Timestamps:462864359/462163474 0x1b96bfe71b8c0e12)] [] [{1 1 []} {1 1 []} {8 10 [27 150 191 231 27 140 14 18]} {0 0 []}] {<nil>}}
tcp payload:[15 0 0 0 3 115 104 111 119 32 100 97 116 97 98 97 115 101 115]

前4个字节是mysql packet head.

前3个字节表示mysql payload 长度15个字节:

15 0 0

第4个字节0,表示序列号0

第5个字节开始是mysql payload body,3表示查询COM_QUERY

接着后面的字节(ASCII码),就是具体的查询语句(即show databases):

115 104 111 119 32 100 97 116 97 98 97 115 101 115

mysql server返回的结果

首先是ACK,其中不包含mysql packet。

PACKET: 56 bytes, wire length 56 cap length 56 @ 2018-10-10 16:17:44.546001 +0800 CST
- Layer 1 (04 bytes) = Loopback {Contents=[2, 0, 0, 0] Payload=[..52..] Family=IPv4}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..32..] Version=4 IHL=5 TOS=0 Length=52 Id=0 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=0 SrcIP=172.24.232.150 DstIP=172.24.232.150 Options=[] Padding=[]}
- Layer 3 (32 bytes) = TCP {Contents=[..32..] Payload=[] SrcPort=3306(mysql) DstPort=51905 Seq=850183053 Ack=1194291177 DataOffset=8 FIN=false SYN=false RST=false PSH=false ACK=true URG=false ECE=false CWR=false NS=false Window=12645 Checksum=10629 Urgent=0 Options=[TCPOption(NOP:), TCPOption(NOP:), TCPOption(Timestamps:462864359/462864359 0x1b96bfe71b96bfe7)] Padding=[]} tcp:&{{[12 234 202 193 50 172 195 141 71 47 111 233 128 16 49 101 41 133 0 0 1 1 8 10 27 150 191 231 27 150 191 231] []} 3306(mysql) 51905 850183053 1194291177 8 false false false false true false false false false 12645 10629 0 [12 234] [202 193] [TCPOption(NOP:) TCPOption(NOP:) TCPOption(Timestamps:462864359/462864359 0x1b96bfe71b96bfe7)] [] [{1 1 []} {1 1 []} {8 10 [27 150 191 231 27 150 191 231]} {0 0 []}] {<nil>}}
tcp payload:[]

接着,返回的是结果集。结果集中包括7个mysql packet。下面逐一分析。

PACKET: 215 bytes, wire length 215 cap length 215 @ 2018-10-10 16:17:44.546415 +0800 CST
- Layer 1 (04 bytes) = Loopback {Contents=[2, 0, 0, 0] Payload=[..211..] Family=IPv4}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..191..] Version=4 IHL=5 TOS=0 Length=211 Id=0 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=0 SrcIP=172.24.232.150 DstIP=172.24.232.150 Options=[] Padding=[]}
- Layer 3 (32 bytes) = TCP {Contents=[..32..] Payload=[..159..] SrcPort=3306(mysql) DstPort=51905 Seq=850183053 Ack=1194291177 DataOffset=8 FIN=false SYN=false RST=false PSH=true ACK=true URG=false ECE=false CWR=false NS=false Window=12645 Checksum=10788 Urgent=0 Options=[TCPOption(NOP:), TCPOption(NOP:), TCPOption(Timestamps:462864359/462864359 0x1b96bfe71b96bfe7)] Padding=[]}
- Layer 4 (159 bytes) = Payload 159 byte(s) tcp:&{{[12 234 202 193 50 172 195 141 71 47 111 233 128 24 49 101 42 36 0 0 1 1 8 10 27 150 191 231 27 150 191 231] [1 0 0 1 1 75 0 0 2 3 100 101 102 18 105 110 102 111 114 109 97 116 105 111 110 95 115 99 104 101 109 97 8 83 67 72 69 77 65 84 65 8 83 67 72 69 77 65 84 65 8 68 97 116 97 98 97 115 101 11 83 67 72 69 77 65 95 78 65 77 69 12 33 0 192 0 0 0 253 1 0 0 0 0 19 0 0 3 18 105 110 102 111 114 109 97 116 105 111 110 95 115 99 104 101 109 97 6 0 0 4 5 109 121 115 113 108 19 0 0 5 18 112 101 114 102 111 114 109 97 110 99 101 95 115 99 104 101 109 97 4 0 0 6 3 115 121 115 7 0 0 7 254 0 0 34 0 0 0]} 3306(mysql) 51905 850183053 1194291177 8 false false false true true false false false false 12645 10788 0 [12 234] [202 193] [TCPOption(NOP:) TCPOption(NOP:) TCPOption(Timestamps:462864359/462864359 0x1b96bfe71b96bfe7)] [] [{1 1 []} {1 1 []} {8 10 [27 150 191 231 27 150 191 231]} {0 0 []}] {<nil>}}
tcp payload:[1 0 0 1 1 75 0 0 2 3 100 101 102 18 105 110 102 111 114 109 97 116 105 111 110 95 115 99 104 101 109 97 8 83 67 72 69 77 65 84 65 8 83 67 72 69 77 65 84 65 8 68 97 116 97 98 97 115 101 11 83 67 72 69 77 65 95 78 65 77 69 12 33 0 192 0 0 0 253 1 0 0 0 0 19 0 0 3 18 105 110 102 111 114 109 97 116 105 111 110 95 115 99 104 101 109 97 6 0 0 4 5 109 121 115 113 108 19 0 0 5 18 112 101 114 102 111 114 109 97 110 99 101 95 115 99 104 101 109 97 4 0 0 6 3 115 121 115 7 0 0 7 254 0 0 34 0 0 0]

mysql packet 1

column count

1 0 0 1 1

前3个字节定义了payload长度为1。

1 0 0

第4个字节1,表示序列号1。

第5个字节开始是payload body,只有1个字节,为1,表示column count 为1.

mysql packet 2

75 0 0 2 3 100 101 102 18 105 110 102 111 114 109 97 116 105 111 110 95 115 99 104 101 109 97 8 83 67 72 69 77 65 84 65 8 83 67 72 69 77 65 84 65 8 68 97 116 97 98 97 115 101 11 83 67 72 69 77 65 95 78 65 77 69 12 33 0 192 0 0 0 253 1 0 0 0 0

列名Database相关信息。

ASCII码字符(Database)

68 97 116 97 98 97 115 101

mysql packet 3

19 0 0 3 18 105 110 102 111 114 109 97 116 105 111 110 95 115 99 104 101 109 97

类似,前4个字节定义了payload长度19和序列号3.

接着,payload中可解析出

row 值为 "information_schema"

mysql packet 4

6 0 0 4 5 109 121 115 113 108

类似,前4个字节定义了payload长度6和序列号4.

接着,payload中可解析出

row 值为 "mysql"

mysql packet 5

19 0 0 5 18 112 101 114 102 111 114 109 97 110 99 101 95 115 99 104 101 109 97

类似,前4个字节定义了payload长度19和序列号5.

接着,payload中可解析出

row 值为 "performance_schema"

mysql packet 6

4 0 0 6 3 115 121 115

类似,前4个字节定义了payload长度4和序列号6.

接着,payload中可解析出

row 值为 "sys"

mysql packet 7

7 0 0 7 254 0 0 34 0 0 0

类似,前4个字节定义了payload长度7和序列号7.

client ACK

不包含mysql packet

PACKET: 56 bytes, wire length 56 cap length 56 @ 2018-10-10 16:17:44.546457 +0800 CST
- Layer 1 (04 bytes) = Loopback {Contents=[2, 0, 0, 0] Payload=[..52..] Family=IPv4}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..32..] Version=4 IHL=5 TOS=0 Length=52 Id=0 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=0 SrcIP=172.24.232.150 DstIP=172.24.232.150 Options=[] Padding=[]}
- Layer 3 (32 bytes) = TCP {Contents=[..32..] Payload=[] SrcPort=51905 DstPort=3306(mysql) Seq=1194291177 Ack=850183212 DataOffset=8 FIN=false SYN=false RST=false PSH=false ACK=true URG=false ECE=false CWR=false NS=false Window=9347 Checksum=10629 Urgent=0 Options=[TCPOption(NOP:), TCPOption(NOP:), TCPOption(Timestamps:462864359/462864359 0x1b96bfe71b96bfe7)] Padding=[]} tcp:&{{[202 193 12 234 71 47 111 233 50 172 196 44 128 16 36 131 41 133 0 0 1 1 8 10 27 150 191 231 27 150 191 231] []} 51905 3306(mysql) 1194291177 850183212 8 false false false false true false false false false 9347 10629 0 [202 193] [12 234] [TCPOption(NOP:) TCPOption(NOP:) TCPOption(Timestamps:462864359/462864359 0x1b96bfe71b96bfe7)] [] [{1 1 []} {1 1 []} {8 10 [27 150 191 231 27 150 191 231]} {0 0 []}] {<nil>}}
tcp payload:[]

参考

COM_QUERY Response

上一篇:cocos creator主程入门教程(一)—— 初识creator


下一篇:JavaScript DOM编程艺术读书笔记(三)