QuantumTunnel:內網穿透服務設計

背景

最近工作中有公網訪問內網服務的需求,便了解了內網穿透相關的知識。發現原理和實現都不復雜,遂產生了設計一個內網穿透的想法。

名字想好了,就叫QuantumTunnel,量子隧道,名字來源於量子糾纏現象。 > 兩個處於量子糾纏的粒子,無論處於多麼遠的距離,當其中一個粒子狀態改變時,另外一個粒子也會做出相應的改變。

QuantumTunnel也取意於此,希望把公網發出來的請求,完整的同步到內網,就像在內網發出的請求,打破網絡的限制。

什麼是內網穿透

什麼是內網穿透?摘自百度百科 > 內網穿透,也即 NAT 穿透,進行 NAT 穿透是爲了使具有某一個特定源 IP 地址和源端口號的數據包不被 NAT 設備屏蔽而正確路由到內網主機。

通俗易懂一點就是一個公網內的機器與不能被公網訪問的機器進行數據交換。 這個不能被公網訪問的機器有可能在某個機房,也有可能在家。

示意圖

典型的應用場景

  1. 公網訪問內網中的某個系統服務:出於安全等因素考慮,機房一般是不能被公網訪問的;要想訪問機房中的某個服務,就需要用到內網穿透;
  2. 開發者電腦接收公網回調:在開發微信業務時,一般會涉及到服務回調,而開發者電腦無法被公網訪問,這時候也需要內網穿透進行橋接。

設計思路

  1. 首先,擺在面前的問題是如何讓公網與內網通信。內網的機器不能被公網訪問但是一般都能夠訪問公網(沒有訪問公網能力的場景不在討論範圍內)。可以利用這一點,讓內網機器主動與公網的服務器建立雙向通信連接,這樣公網服務器就具備了往內網服務器發送數據的能力;
  2. 其次,要思考怎麼才能讓用戶請求到達這個雙向通信通道。此時就需要一個用戶側的服務器,專門處理來自用戶的請求,並將其轉發到雙向通信通道;
  3. 上面兩個步驟完成後,用戶請求就來到了內網,此時需要一個客戶端代替用戶進行真正的請求,拿到返回結果。

歸納總結一下。爲了實現內網穿透能力,內網穿透服務中應該有的幾個角色:

  1. 用戶服務器:處理用戶過來的請求,將用戶請求轉發給代理服務器;
  2. 代理服務器:接收用戶服務器過來的請求數據並轉發給往代理客戶端;接收代理客戶端的結果數據並返回給用戶服務器;
  3. 代理客戶端:接收代理服務器的請求數據並且進行真正的請求,拿到結果數據後返回給代理服務器。

架構圖

按照上述思路,內網穿透的架構應該是這樣的: 架構圖

我們再次梳理一下參與到內網穿透服務的各個角色:

  1. 用戶客戶端:真實的請求發起方;
  2. 內網穿透-用戶服務端:接收用戶客戶端發起的請求;並將請求轉發給代理服務端;
  3. 內網穿透-代理服務端:與代理客戶端保持一個連接通道用於傳輸數據;並且將請求通過該通道傳輸數據到proxy-client;
  4. 內網穿透-代理客戶端:從通道中接收來自代理服務端的請求數據,並且發起真正的請求。拿到請求結果後再通過該通道寫回到代理服務端;
  5. 目標服務器:目標服務器,即被代理的服務器。

時序圖

順着這個思路,我們來畫一下時序圖。

內網穿透時序圖

時序圖分爲兩部分:

  1. 首先,代理服務器和代理客戶端建立了一條長連接,用於數據的傳輸,這個很關鍵。 因爲代理服務器(公網)無法直接訪問代理客戶端,必須由代理客戶端主動向代理服務器發起連接請求,從而建立一條可以雙向通信的連接通道,利用雙向通信的能力實現代理服務器主動向代理客戶端發送請求的能力

  2. 然後是一次內網穿透請求的流程。 要注意的是對raw request(response)的處理:raw request -> proxy request -> raw request,經歷了從原始請求到代理請求再到原始請求的封裝和解析過程。 爲什麼要有這個協議轉換過程?要實現協議無侵入(如http、ws)的目標,只能在現有協議上擴展請求。如內網穿透http協議,可以把目標地址和目標端口放在header中進行擴展,內網穿透-用戶服務器再把相關的參數給解析出來,從而知道目標地址和端口是什麼。這樣處理的好處也顯而易見,在原來的框架、代碼不變的情況下,增加幾個參數就可以用上內網穿透服務。

大家可以瞭解一下這兩個內網穿透的實現,natx毒刺,我在設計實現過程中參考了他們的一些實現。

具體實現

結合上面的架構圖、時序圖,要想實現應用層協議無侵入,需要一個能直接在傳輸層進行流量代理的工具。在網絡傳輸領域大火的netty便進入了我們的視線,支持TCP、UDP流量轉發,擁有豐富的應用層協議插件,更重要的是發送數據非常方便,只需要往Channel裏面寫入數據就行。

對於具體實現,本文暫不討論,計劃放在QuantumTunnel系列博客中的第二篇展開。

下面看看實現的效果。

效果

假設南京本地寶的服務器在內網,我們現在要訪問它的新聞諮詢頻道。原始鏈接爲:http://nj.bendibao.com/news/

把目標服務器替換成南京本地寶服務器,重新畫一下架構圖和時序圖:

  1. 架構圖

訪問架構圖

  1. 時序圖

訪問時序圖

  1. 訪問結果

訪問結果

從返回的結果可以看到,通過本地的8090端口,訪問到了南京本地寶的服務器,說明整個鏈路成功走通。 這裏解釋一下訪問結果中的幾個參數 > proxyHost:被代理的服務器地址;proxyPort:被代理的服務器端口

好了,本篇就聊到這裏。後面會推出一個系列博客聊一下基於Netty的實現方案,以及業務隔離、服務高可用的一個探索等好玩的東西。

掃碼關注,一起進步

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