與世界分享我剛編的mysql http隧道工具-hersql原理與使用

2023-05-25 06:02:37

原文地址:https://blog.fanscore.cn/a/53/

1. 前言

本文是與世界分享我剛編的轉發ntunnel_mysql.php的工具的後續,之前的實現有些拉胯,這次重構了下。需求背景是為了在本地macbook上通過開源的mysql視覺化使用者端(dbeaver、Sequel Ace等)存取我司測試環境的mysql,整個測試環境的如圖所示:

那麼就有以下幾種方式:

  • 使用者端直連mysql
    #Pass# 測試環境mysql只提供了內網ip,只允許測試環境上的機器連線,因此不可行
  • 通過ssh隧道連線
    #Pass# 測試環境機器倒是可以ssh上去,但是隻能通過堡壘機接入,且堡壘機不允許ssh隧道,因此不可行
  • navicat http隧道連線
    #Pass# 測試環境有機器提供了公網ip開放了http服務,因此技術上是可行的,但navicat非開源免費軟體,我司禁止使用,因此不可行
  • 測試環境選一臺機器建立mysql代理轉發請求
    #Pass# 測試環境機器只開放了80埠,且已被nginx佔用,因此不可行
  • 內網穿透
    這個想法很好,下次不要再想了

既然上面的方式都不行,那怎麼辦呢?因此我產生了一個大膽的想法

2. 一個大膽的想法

大概架構如下

首先,在本地pc上啟動一個sidecar程序,該程序監聽3306埠,實現mysql協定,將自己偽裝為一個mysql server。本地pc上的mysql使用者端連線到sidecar,傳送請求封包給sidecar,從sidecar讀取響應包。

然後在測試環境某臺機器上啟動transport程序,該程序啟動http服務,由nginx代理轉發請求,相當於監聽在80埠,然後連線到測試環境的mysql server。

sidecar會將來自使用者端的請求包通過http請求轉發給transporttransport將請求包轉發到測試環境對應的mysql server,然後讀取mysql的響應封包,然後將響應封包返回給sidecarsidecar再將響應包返回給mysql使用者端。

遵循上述的基本原理,我將其實現出來: https://github.com/Orlion/hersql。但是在描述hersql的實現細節之前我們有必要了解下mysql協定

3. mysql協定

mysql使用者端與伺服器端互動過程主要分為兩個階段:握手階段與命令階段。互動流程如下:

在最新版本中,握手過程比上面要複雜,會多幾次互動

3.1 握手階段

在握手階段,3次握手建立tcp連線後伺服器端會首先傳送一個握手初始化包,包含了

  • 協定版本號:指示所使用的協定版本。
  • 伺服器版本:指示MySQL伺服器版本的字串。
  • 連線ID:在當前連線中唯一標識使用者端的整數。
  • 亂資料:包含一個隨機字串,用於後續的身份驗證。
  • 伺服器支援的特性標誌:指示伺服器支援的使用者端功能的位掩碼。
  • 字元集:指示伺服器使用的預設字元集。
  • 預設的身份驗證外掛名(低版本沒有該資料)

隨後使用者端會傳送一個登入認證包,包含了:

  • 協定版本號:指示所使用的協定版本。
  • 使用者名稱:用於身份驗證的使用者名稱。
  • 加密密碼:使用者端使用伺服器端返回的亂數對密碼進行加密
  • 資料庫名稱:連線後要使用的資料庫名稱。
  • 使用者端標誌:使用者端支援的功能的位掩碼。
  • 最巨量資料包大小:使用者端希望接收的最巨量資料包大小。
  • 字元集:使用者端希望使用的字元集。
  • 外掛名稱:使用者端希望使用的身份驗證外掛的名稱。

伺服器端收到使用者端發來的登入認證包驗證通過後會傳送一個OK包,告知使用者端連線成功,可以轉入命令互動階段

在mysql 8.0預設的身份驗證外掛為caching_sha2_password,低版本為mysql_native_password,兩者的驗證互動流程有所不同個,caching_sha2_password在快取未命中的情況下還會多幾次互動。另外如果伺服器端與使用者端的驗證外掛不同的話,也是會多幾次互動。

3.2 命令階段

在命令階段,使用者端會傳送命令請求包到伺服器端。封包的第一個位元組標識了當前請求的型別,常見的命令有:

  • COM_QUERY命令,執行SQL查詢語句。
  • COM_INIT_DB命令,連線到指定的資料庫。
  • COM_QUIT命令,關閉MySQL連線。
  • COM_FIELD_LIST命令,列出指定表的欄位列表。
  • COM_PING命令,向MySQL伺服器傳送PING請求。
  • COM_STMT_系列預處理語句命令

請求響應的模式是使用者端會發一個請求包,伺服器端會回覆n(n>=0)個響應包

最後使用者端斷開連線時會主動傳送一個COM_QUIT命令包通知伺服器端斷開連線

4. hersql資料流轉過程

在瞭解mysql協定之後我們就可以來看下hersql的資料流轉過程了。

5. hersql使用

上面介紹了一堆原理性的東西,那麼如何使用呢?

5.1 在一臺能夠請求目標mysql server的機器上部署hersql transport

首先你需要下載下來hersql的原始碼:https://github.com/Orlion/hersql,還需要安裝下golang,這些都完成後你就可以啟動hersql transport了。但是先彆著急,我先解釋下transport的組態檔tranport.example.yaml:

server:
  # transport http服務監聽的地址
  addr: :8080

log:
  # 標準輸出的紀錄檔的紀錄檔級別
  stdout_level: debug
  # 檔案紀錄檔的紀錄檔級別
  level: error
  # 檔案紀錄檔的檔案地址
  filename: ./storage/transport.log
  # 紀錄檔檔案的最大大小(以MB為單位), 預設為 100MB。紀錄檔檔案超過此大小會建立個新檔案繼續寫入
  maxsize: 100
  # maxage 是根據檔名中編碼的時間戳保留舊紀錄檔檔案的最大天數。 
  maxage: 168
  # maxbackups 是要保留的舊紀錄檔檔案的最大數量。預設是保留所有舊紀錄檔檔案。
  maxbackups: 3
  # 是否應使用 gzip 壓縮旋轉的紀錄檔檔案。預設是不執行壓縮。
  compress: false

你可以根據你的需求修改設定,然後就可以啟動transport

$ go run cmd/transport/main.go -conf=transport.example.yaml

一般情況下都是會先編譯為可執行檔案,由systemd之類的工具託管transport程序,保證transport存活。這裡簡單期間直接用go run起來

5.2 在你本地機器部署啟動hersql sidecar

同樣的,你需要下載下來hersql的原始碼:https://github.com/Orlion/hersql,提前安裝好golang。修改下sidecar的組態檔sidecar.example.yaml:

server:
  # sidecar 監聽的地址,之後mysql client會連線這個地址
  addr: 127.0.0.1:3306
  # transport http server的地址
  transport_addr: http://x.x.x.x:xxxx
log:
  # 與transport設定相同

就可以啟動sidecar

$ go run cmd/sidecar/main.go -conf=sidecar.example.yaml

同樣的,一般情況下也都是會先編譯為可執行檔案,mac上是launchctl之類的工具託管sidecar程序,保證sidecar存活。這裡簡單期間直接用go run起來

5.3 使用者端連線

上面的步驟都執行完成後,就可以開啟mysql使用者端使用了。資料庫地址和埠號需要填寫sidecar組態檔中的addr地址,sidercar不會校驗使用者名稱和密碼,因此使用者名稱密碼可以隨意填寫

重點來了: 資料庫名必須要填寫,且必須要按照以下格式填寫

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]

舉個例子:

root:123456@tcp(10.10.123.123:3306)/BlogDB

如圖所示:

5.4 舉個例子

目標mysql伺服器

  • 地址:10.10.123.123:3306
  • 資料庫:BlogDB
  • 使用者名稱:root
  • 密碼:123456

可以直連目標mysql伺服器的機器

  • 地址:10.10.123.100
  • 開放埠:8080

那麼transport可以設定為

server:
  addr: :8080

sidecar可以設定為

server:
  addr: 127.0.0.1:3306
  transport_addr: http://10.10.123.100:8080

使用者端連線設定

  • 伺服器地址:127.0.0.1
  • 埠: 3306
  • 資料庫名root:123456@tcp(10.10.123.123:3306)/BlogDB

6. 參考資料

如果hersql對你有幫助歡迎點個star