frp 原理與代碼分析(1):ssh訪問內網機器

以內網穿透,通過ssh訪問內網機器爲例,講解frp的原理。

簡單的原理如下:

簡單說,就是建立上圖的三個通道,並把三個通道進行連通,即實現了ssh的內網穿透。ssh代理的簡單流程如下:

1. frpc登錄frps,frps要求frpc與其建立新的工作連接。frpc建立新的工作連接。

2. frpc請求frps建立Tcp代理,frps建立Tcp代理。

3. 用戶連接frps建立的Tcp代理,frps通知frpc有用戶連接ssh,frpc與本地ssh服務建立Tcp連接。

4. frps連通用戶連接和(frps和frpc建立的新的工作連接),frpc連通本地的ssh Tcp連接和(frps和frpc的建立的新的工作連接),至此,通道打通。

frpc客戶端登錄frps,開啓Tcp代理;用戶ssh登錄。服務端frps和客戶端frpc交互流程如下:

frps與frpc交互流程圖

 

1. frpc和frps建立Tcp連接,frpc通過yamux,打開一個數據流stream(暫時命名爲stream 1),在該數據流上發送Login消息給frps。(yamux 依賴底層可靠的連接(tcp、unix domain sockets),在可靠的連接之上提供了面向流 I/O 多路複用,其核心思想是在發送數據的時候增加頭部信息,附加一層協議。 在 yamux 中,一條連接稱爲 session,一個 session 可以開啓多個數據流,數據流稱爲 stream。)

yamux I/O多路複用

2. frps接收到frpc打開的stream上的Login消息,創建control控制器,control負責該stream上消息的收發和處理;啓動control,control啓動後響應LoginResp消息,併發送ReqWorkConn消息,該消息的作用是,要求frpc主動與frps開啓一個或者多個stream,這些stream會被用於後面用戶數據的轉發。

3. frpc收到該消息後,主動開啓stream,開啓的stream相當於數據通道,第一步frpc和frps開啓的stream相當於控制通道,控制通道用於傳輸控制消息。

frpc每收到一條ReqWorkConn消息,開啓一個新的線程,在該線程中主動與frps開啓一個數據流,並在該數據流上發送一個NewWorkConn消息,發送完成後,阻塞等待該數據流上的StartWorkConn消息。

4. frps收到frpc打開的stream的上NewWorkConn消息,把該stream放入連接池(數據流池)中。

5. frpc在stream 1上發送NewProxy消息,消息內容包括(remote_port,proxy_name,proxy_type等,remote_port是Tcp代理監聽的端口,即用戶即將連接的ssh端口;proxy_type是Tcp)。

6. frps收到stream 1上frpc發來的NewProxy消息,frps的control控制器負責處理該消息。T

control根據NewProxy消息內容,創建Tcp代理,在NewProxy中的remote_port上開啓Tcp監聽,等待用戶ssh客戶端主動連接。

7. frps創建的Tcp代理,接收到用戶的ssh Tcp連接,在第四步中的連接池中,取出一個stream,在該stream上發送一個StartWorkConn消息,通知frpc該stream開始工作。並把用戶連接與該stream進行數據連通(即相互把從自己連接上收到的數據,通過對方的連接發送出去,實現一種管道互通的效果)。

8. frpc端,對應的stream上收到該消息,阻塞等待StartWorkConn消息的線程,因爲收到該消息,開始主動與本地ssh(127.0.0.1:22)建立一個Tcp連接,並把stream和該Tcp連接進行數據連通。至此,所用tcp通道已經打通,用戶ssh可以正常登錄了。

注:這種數據連通是阻塞的,直到任何一個連接上發生錯誤,發生錯誤後,會同時關閉兩個連接。因爲一個完整的內網穿透ssh通道,包含三個TCP連接(①用戶創建的ssh連接,②rps和frpc建立的連接,③frpc和ssh服務器建立的連接。①和②連通,②和③連通),任何一個連接關閉,其他的連接也會感知到,也會一同關閉。即代碼中Join函數的精妙之處。

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