【新晉開源專案】內網穿透神器[中微子代理] 加入 Dromara 開源社群

2023-02-02 21:00:40

1、關於作者

  • dromara開源組織成員,dromara/neutrino-proxy專案作者
  • 名稱:傲世孤塵、雨韻詩澤
  • 名言:
    • 紮根土壤,心向太陽。積蓄能量,綻放微光。
    • 拘濁酒邀明月,借赤日暖蒼穹。喻萬物為星斗,化滄海成詩篇。
    • 還生命以坦然,遺滄海以一笑。
  • 微訊號:yuyunshize
  • Gitee: gitee.com/asgc

2、專案簡介

  • 中微子代理(neutrino-proxy) 是一款基於netty的內網穿透神器。該專案採用最為寬鬆的MIT協定,因此您可以對它進行復制、修改、傳播並用於任何個人或商業行為。
  • 演示環境:
  • 該開源版本針對開發者個人,不提供任何付費服務。上面提供的地址、賬號僅用於演示,已提供現成的license供大家測試。
  • 市面上基於內網穿透的常見產品有:花生殼、TeamView、cpolar等。
  • 該專案的目標是開啟內網穿透功能黑盒,讓更多感興趣的朋友能更簡單、低成本的掌握內網穿透技術。
  • 學習、使用過程中,有任何問題都可以通過微信(通過上面的微訊號,或掃描結尾的二維條碼)與筆者聯絡。同時,若該專案對您有所幫助,也請大家不吝轉發推薦。

3、目錄&檔案說明

├── data.db 'sqlite資料庫檔案。若未設定mysql,預設使用sqlite,專案首次啟動會自動初始化sqlite資料庫。
├── docs '專案相關的一些檔案
├── ├── Aop.MD '框架層Aop機制、使用說明
├── └── Channel.MD '內網穿透實現原理、代理實現流程說明
├── lib '專案開啟了將自動生成的類儲存到本地後,執行過程中動態生成的類自動儲存到此處,方便學習、偵錯
├── neutrino-core '一套手寫的基於netty的框架,相當於簡易版的SpringBoot + Mybatis + xxljob,計劃後期分離為單獨開源專案維護
├── neutrino-proxy-admin '基於vue-element-admin開發的一個管理系統,用於視覺化操作埠對映、代理資料實時監控
├── neutrino-proxy-client '基於netty的代理使用者端,用於和伺服器端互動、轉發內網資料
├── neutrino-proxy-core '代理相關的公共程式碼(協定、常數)
├── neutrino-proxy-server '基於netty的代理伺服器端,用於和客戶段互動,將使用者端轉發的內網資料轉發至外網埠
└── todolist.MD '近期的開發計劃
複製程式碼

4、專案亮點

  • 效能:基於netty,天然擁有netty的高效能優勢
  • 學習:除netty之外,只依賴了最基本的紀錄檔、資料庫驅動/連線池、json等jar包,代理層程式碼量非常精簡。極其適合java初學者用來學習和掌握Web框架底層原理、內網穿透實現機制。
  • 偵錯:只需要安裝jdk8,甚至連資料庫都無需考慮,即可直接在本地執行伺服器端+使用者端,偵錯代理流程。儘可能減少前期步驟,確保大家能更快上手。
  • 測試:針對框架層封裝(如:AOP、Web容器、ORM、排程管理等),提供了豐富的測試程式碼。

5、執行環境

以下版本均為筆者開發時實際的使用版本

  • Node:v13.12.0
  • Java:1.8.0_351
  • Mysql:8.0.31 (非必需,使用sqlite則無需考慮資料庫)
  • Nginx:1.21.4 (非必需,可直接使用伺服器端專案提供的靜態資源服務)

6、使用方法

6.1、打包

可直接前往Gitee倉庫發行版頁面下載所需版本已打好的包。 若需手動打包,則可參照下面的執行命令:

# 伺服器端打包
mvn clean install -U -pl neutrino-proxy-server -am -Dmaven.test.skip=true

# 使用者端打包
clean install -U -pl neutrino-proxy-client -am -Dmaven.test.skip=true

# 管理後臺前端專案打包(本地環境,local改為dev則為dev環境,同時需要修改config目錄下面的環境設定)
npm run build:local
複製程式碼

6.2、部署

6.2.1、伺服器端部署

使用常規的jar包部署方式即可,如:java -jar xxxx

6.2.2、管理後臺部署

Nginx方式部署(推薦):

server {
        listen 9527;
        server_name localhost;

	#開啟gzip
	gzip  on;
	#低於1kb的資源不壓縮
	gzip_min_length 1k;
	#壓縮級別1-9,越大壓縮率越高,同時消耗cpu資源也越多,建議設定在5左右。
	gzip_comp_level 5;
	#需要壓縮哪些響應型別的資源,多個空格隔開。不建議壓縮圖片.
	gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
	#設定禁用gzip條件,支援正則。此處表示ie6及以下不啟用gzip(因為ie低版本不支援)
	gzip_disable "MSIE [1-6]\.";
	#是否新增「Vary: Accept-Encoding」響應頭
	gzip_vary on;

	location / {
            root  /work/projects/neutrino-proxy-server/neutrino-proxy-admin/dist;
            try_files $uri $uri/ /index.html;
            add_header Last-Modified $date_gmt;
	}
}
複製程式碼

在沒有Nginx時,為了快速體驗代理效果,可直接使用伺服器端專案提供的靜態資源服務。 直接將neutrino-proxy-admin打包後的檔案解壓放在neutrino-proxy-server.jar同級別目錄下即可。 例如:伺服器端設定的web埠為8080,則存取http://伺服器端IP:8080, 則會直接解析渲染neutrino-proxy-server.jar同級別目錄下neutrino-proxy-admin/dist/index.html

需要注意的是,使用伺服器端自帶的靜態資源服務時,由於框架目前未支援快取、gzip壓縮,所以存取速度沒有使用nginx快,正式使用推薦用nginx。

6.3、設定

6.3.1、設定埠池

埠池的作用是將代理服務需要對外暴露的埠進行集中管理,方便安全組設定時統一操作。

本專案為了簡化首次設定,預設初始化資料會將9101~9120的所有埠加入埠池。 可以在伺服器端專案sql設定(port_pool.data.sql檔案)中自行修改初始化資料,也可以執行後在埠池管理頁面手動維護。

首次使用如果為了快速體驗,建議直接使用預設埠池,則無需任何設定。

6.3.2、設定使用者

使用者是登入管理後臺的身份主體,同時也是持有license的身份主體,用於支援代理連線的合法性認證。

本專案為了簡化首次設定,預設初始化admin、visitor兩個使用者,預設密碼為123456。 可以在伺服器端專案sql設定(user.data.sql檔案)中自行修改初始化資料,也可以執行後在使用者管理頁面手動維護。

首次使用如果為了快速體驗,建議直接使用預設使用者,則無需任何設定。

6.3.3、設定License

License是使用者端連線代理伺服器端時所需要的唯一合法憑證,一個License同時只能被一個使用者端使用。

本專案為了簡化首次設定,預設為每個使用者初始化了一些license。 可以在伺服器端專案sql設定(license.data.sql檔案)中自行修改初始化資料,也可以執行後在License管理頁面手動維護。

首次使用如果為了快速體驗,建議直接使用預設License,則無需任何設定。

6.3.4、設定埠對映

埠對映是代理的基本單元,一個外網埠在同一時刻被唯一的對映到一個內網IP+埠。所有流出該外網埠的流量都轉發自對應的內網埠,同理所有流入該外網埠的流量都會轉發到對應的內網埠。

本專案為了簡化首次設定,預設為每個使用者初始化了一些埠對映。可以在伺服器端專案sql設定(port_mapping.data.sql檔案)中自行修改初始化資料,也可以執行後在埠對映管理頁面手動維護。

首次使用如果為了快速體驗,建議直接使用預設埠對映,則無需任何設定。

6.4、開啟代理

上述步驟完成後,就可以開始代理自己的區域網裝置了。

比如現在有一個license:a123456,該license設定了一個或多個埠對映,其中包含9010到localhost:8080的對映(localhost表示代理使用者端所在主機的埠,可以換成使用者端所在區域網的任何IP)。此時修改使用者端設定的伺服器端ip、license等啟動使用者端,就可以開啟代理了,埠對映管理對應的記錄線上狀態為"線上"則證明代理成功建立。

該license設定也可以通過使用者端啟動引數、啟動後引導式輸入、外接設定提供,為了簡化首次體驗門檻,這裡直接提供一個外接設定模版:

{
	"jksPath":"classpath:/test.jks",
	"licenseKey":"b0a907332b474b25897c4dcb31fc7eb6",
	"serverIp":"localhost",
	"serverPort":9002,
	"sslEnable":true
}
複製程式碼

修改上述json中的licenseKey,serverIp、serverPort、sslEnabled後,儲存檔案命名為.neutrino-proxy-client.json,放在使用者端當前目錄下(jar包啟動時,放在jar包同級別目錄下。idea啟動時,放在專案根目錄下),然後直接啟動使用者端。

此時通過存取外網ip+埠,可以成功存取內網服務。通過此方式,可以代理任何基於TCP之上的協定,如:socket、websocket、http、ftp、ssh等。

7、開發&偵錯

篇幅所限,此處不便贅述管理後臺相關的開發,有vue基礎的童鞋基本都可以自行開發。伺服器端的初始化資料足夠偵錯工作,開發過程無需單獨在管理頁面操作。

與SpringBoot專案類似,使用者端、伺服器端專案均由一個入口類完成整個專案的啟動,分別為ProxyClientProxyServer

內建設定採用yml風格,主要涉及Http埠、靜態資源路徑、協定引數、代理伺服器端埠、jks證書、資料來源、license等。 整個專案基於neutrino-core,風格類似於SpringBoot。筆者不喜歡因過分炫技而引入過多花式操作,因為專案的定位是個人開發者,且滿足使用的同時兼顧學習其原理的需求。基本使用方式與SpringBoot類似,儘可能降低首次學習成本。

neutrino-core專案test目錄下包含眾多核心封裝的測試程式碼,通過偵錯這些程式碼,能儘可能減少大家學習的障礙。

8、執行截圖

License管理:

埠對映管理:

埠池管理:

使用者管理:

9、迭代進度&未來計劃

2022-06-16 第一個完整可用版本釋出(無管理後臺、無DB,純設定實現)起,該專案已具備完整的內網穿透功能。經過後續的不斷重構,初步完成了以下迭代:

  • 使用sqlite取代純設定,增加管理後臺介面。解決修改埠對映需要重新打包的問題。
  • 增加mysql支援。初學時,直接預設使用sqlite,可以專注於學習代理相關細節而不必額外安裝、設定資料庫。有了自己的伺服器後,可設定使用mysql,完全相容。
  • 增加埠池管理。方便伺服器統一設定安全組,避免暴露的外網埠雜亂無章。
  • 整合排程管理。個人版專案自帶排程管理,降低學習、使用成本。無需部署、接入其他排程服務。
  • 增加簡單的遊客許可權限制。個人版專案無需許可權管理,但是為了演示需要,同時避免遊客篡改管理員資料。
  • 封裝一套類似於SpringBoot + Mybatis的簡化框架,用於支撐上層代理專案,減少外部依賴,為後期孵化一個開源框架做準備。

由於筆者工作之餘才能進行開發,可投入時間不固定。截至目前(2023-02),該專案2.0版本仍未釋出,基於此未來的計劃如下:

  • 完成2.0版本釋出(還剩下報表管理、首頁圖表功能)。
  • 底層框架全部重構。
  • 分離出一個開源框架專案,並持續維護。
  • 思考或著手基於內網穿透的產品開發,包括但不限於內網穿透SaaS服務、堡壘機。

10、聯絡我們

筆者時間、能力有限,且開源專案非一朝一夕之事,存在眾多問題亦在所難免。使用、學習過程中有任何問題歡迎大家與我聯絡。

對專案有什麼想法或者建議,可以加我微信 yuyunshize 拉交流群,或者建立issues,一起完善專案