mysql協議分析2---認證包

主人看到navicat和mysql在那嘻嘻哈哈,眉來眼去的,好不快樂,忽然也想自己寫個程序,直接去訪問Mysql,雖然現在已經有很多現成的中間件可以直接拿來用了,程序只要負責寫sql語句就行了,但是主人想要自己通過mysql協議直接和mysql通訊,一窺究竟。於是主人找到Mysql說:親愛的mysql,我以前和你交流總要通過第三方的驅動在中間傳話,總感覺我們之間還有一個隔閡,有些話也不方便說,我現在有些心裏話想直接和你交流。。。你說行嗎?

 

mysql說:當然行啊,mysql受寵若驚,要和我打交道有多種方法比如:TCP/IP,TLS/SSL,Unix Sockets,Shared Memory,Named pipes等,那我們就用TCP/IP的方吧。用tcp協議就繞不開三次握手連接和四次握手斷開,所以呢你和我連接的第一件事就是三次握手連接。

 

主人尷尬的笑了笑,tcp的三次握手聽到聽說過很多次,但是從沒有真正的理解。。。

 

mysql從身後丟過來一個便籤:這裏有篇文章可以參考下:https://www.cnblogs.com/zhanyd/p/9877762.html

主人謝道,還是你體貼,剛開始navicat和你連接的時候,我是輸入了主機地址,用戶名,密碼的,你們之間是怎麼驗證的呢?

 

mysql說:好問題,所有的客戶端和我連接首先都要先經過我的認證,我和客戶端一次正常的交互過程如下:

1. 三次握手建立 TCP 連接。

2. 建立 MySQL 連接,也就是認證階段。
    服務端 -> 客戶端:發送握手初始化包 (Handshake Initialization Packet)。
    客戶端 -> 服務端:發送驗證包 (Client Authentication Packet)。
    服務端 -> 客戶端:認證結果消息。

3. 認證通過之後,客戶端開始與服務端之間交互,也就是命令執行階段。
    客戶端 -> 服務端:發送命令包 (Command Packet)。
    服務端 -> 客戶端:發送迴應包 (OK Packet, or Error Packet, or Result Set Packet)。

4. 斷開 MySQL 連接。
    客戶端 -> 服務器:發送退出命令包。

5. 四次握手斷開 TCP 連接。

 

我專門搞了個認證報文格式,我會按照以下的格式給客戶端發送數據,然後客戶端要根據這裏面的內容給我返回驗證包,然後我判斷是否有權限登錄:

 

官方的文檔是這樣子滴:

 

 

感覺不直觀,在網上找到一個更直觀的圖:

 

具體解釋如下:

  • protocol_version (1) -- 0x0a protocol_version

    第一個字節表示協議版本號

  • server_version (string.NUL) -- human-readable server version

    服務器版本號,字符串遇到Null結束

  • connection_id (4) -- connection id

     服務器線程id

  • auth_plugin_data_part_1 (string.fix_len) -- [len=8] first 8 bytes of the auth-plugin data

    第一部分8個字節的挑戰隨機數,後面還有第二部分

  • filler_1 (1) -- 0x00

    填充位0x00

  • capability_flag_1 (2) -- lower 2 bytes of the Protocol::CapabilityFlags (optional)

    服務器權能標誌(低位2個字節)

  • character_set (1) -- default server character-set, only the lower 8-bits Protocol::CharacterSet (optional)

    This character set” value is really a collation ID but implies the character set; see the Protocol::CharacterSet description.

    字符編碼

  • status_flags (2) -- Protocol::StatusFlags (optional)

    服務器狀態

  • capability_flags_2 (2) -- upper 2 bytes of the Protocol::CapabilityFlags

    服務器權能標誌(高位2個字節)

  • auth_plugin_data_len (1) -- length of the combined auth_plugin_data, if auth_plugin_data_len is > 0

    挑戰隨機數的長度

  • string[10]     reserved (all [00])

    10個字節的保留位,都是00

  • auth_plugin_data_part_2

    挑戰隨機數的第二部分,通常是12字節

  • 挑戰隨機數結束標誌00

  • auth_plugin_name (string.NUL) -- name of the auth_method that the auth_plugin_data belongs to

            認證插件的名稱,null結尾(這部分上面的圖表裏沒有加進去)

 

 

 

主人聽完後,躍躍欲試,很想驗證下Mysql說的是不是真的,於是他找到了密友Wiresshark,讓他監聽下navicat和mysql之間的認證包,Wiresshark很快就完成了任務,把結果呈上來了:

具體先看服務器發送過來的第一個包:

 

主人一看,居然和mysql說的一模一樣,好神奇。。。

mysql笑道:那當然,我還能騙你不成。我發給客戶端收到後,客戶端就要返回認證包給我驗證啦,是驢是馬我一眼就能認出來了哦,客戶端返回給我要遵循以下的格式:

 

Fields

  • capability_flags (4) -- capability flags of the client as defined in Protocol::CapabilityFlags

    客戶端權能標誌

  • max_packet_size (4) -- max size of a command packet that the client wants to send to the server

    報文的最大字節數

  • character_set (1) -- connection's default character set as defined in Protocol::CharacterSet.

    字符集編碼

  • username (string.fix_len) -- name of the SQL account which client wants to log in -- this string should be interpreted using the character set indicated by character set field.

    用戶名

  • auth-response (string.NUL) -- opaque authentication response data generated by Authentication Method indicated by the plugin name field

    用戶認證信息,即密碼明文和挑戰隨機數加密後的token

  • database (string.NUL) -- initail database for the connection -- this string should be interpreted using the character set indicated by character set field.

    數據庫名稱

  • auth plugin name (string.NUL) -- the Authentication Method used by the client to generate auth-response value in this packet. This is an UTF-8 string.

    認證方法

主人抓包的結果:

 

mysql收到了主人發過來的認證包:主人,經過驗證用戶名密碼都是正確的,可以登錄了,我要返回一個ok報文,告訴你操作成功了哦,報文結構如下:

 

 

  • header:

    OK: header = 0 and length of packet > 7

    header=0並且報文長度>7表示當前是ok報文

    EOF: header = 0xfe and length of packet < 9

     header=0xfe並且報文長度<9表示當前是eof報文

     

主人抓包的結果:

header = 0,表示這個是個ok報文,status_flags(server status)= 02表名設置自動提交成功。

 

 

主人很高興:這是不是說明,我和你的連接成功了呀?

mysql:恭喜你連接成功了,我們走出了第一步,接下來你就可以發送命令讓我執行了喲。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章