├── 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 '近期的開發計劃
複製程式碼
以下版本均為筆者開發時實際的使用版本
Node
:v13.12.0Java
:1.8.0_351Mysql
:8.0.31 (非必需,使用sqlite則無需考慮資料庫)Nginx
:1.21.4 (非必需,可直接使用伺服器端專案提供的靜態資源服務)可直接前往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
複製程式碼
使用常規的jar包部署方式即可,如:java -jar xxxx
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。
埠池的作用是將代理服務需要對外暴露的埠進行集中管理,方便安全組設定時統一操作。
本專案為了簡化首次設定,預設初始化資料會將9101~9120的所有埠加入埠池。 可以在伺服器端專案sql設定(port_pool.data.sql檔案)中自行修改初始化資料,也可以執行後在埠池管理頁面手動維護。
首次使用如果為了快速體驗,建議直接使用預設埠池,則無需任何設定。
使用者是登入管理後臺的身份主體,同時也是持有license的身份主體,用於支援代理連線的合法性認證。
本專案為了簡化首次設定,預設初始化admin、visitor兩個使用者,預設密碼為123456。 可以在伺服器端專案sql設定(user.data.sql檔案)中自行修改初始化資料,也可以執行後在使用者管理頁面手動維護。
首次使用如果為了快速體驗,建議直接使用預設使用者,則無需任何設定。
License是使用者端連線代理伺服器端時所需要的唯一合法憑證,一個License同時只能被一個使用者端使用。
本專案為了簡化首次設定,預設為每個使用者初始化了一些license。 可以在伺服器端專案sql設定(license.data.sql檔案)中自行修改初始化資料,也可以執行後在License管理頁面手動維護。
首次使用如果為了快速體驗,建議直接使用預設License,則無需任何設定。
埠對映是代理的基本單元,一個外網埠在同一時刻被唯一的對映到一個內網IP+埠。所有流出該外網埠的流量都轉發自對應的內網埠,同理所有流入該外網埠的流量都會轉發到對應的內網埠。
本專案為了簡化首次設定,預設為每個使用者初始化了一些埠對映。可以在伺服器端專案sql設定(port_mapping.data.sql檔案)中自行修改初始化資料,也可以執行後在埠對映管理頁面手動維護。
首次使用如果為了快速體驗,建議直接使用預設埠對映,則無需任何設定。
上述步驟完成後,就可以開始代理自己的區域網裝置了。
比如現在有一個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等。
篇幅所限,此處不便贅述管理後臺相關的開發,有vue基礎的童鞋基本都可以自行開發。伺服器端的初始化資料足夠偵錯工作,開發過程無需單獨在管理頁面操作。
與SpringBoot專案類似,使用者端、伺服器端專案均由一個入口類完成整個專案的啟動,分別為ProxyClient
、ProxyServer
。
內建設定採用yml風格,主要涉及Http埠、靜態資源路徑、協定引數、代理伺服器端埠、jks證書、資料來源、license等。 整個專案基於neutrino-core
,風格類似於SpringBoot。筆者不喜歡因過分炫技而引入過多花式操作,因為專案的定位是個人開發者,且滿足使用的同時兼顧學習其原理的需求。基本使用方式與SpringBoot類似,儘可能降低首次學習成本。
neutrino-core
專案test目錄下包含眾多核心封裝的測試程式碼,通過偵錯這些程式碼,能儘可能減少大家學習的障礙。
License管理:
埠對映管理:
埠池管理:
使用者管理:
從2022-06-16
第一個完整可用版本釋出(無管理後臺、無DB,純設定實現)起,該專案已具備完整的內網穿透功能。經過後續的不斷重構,初步完成了以下迭代:
由於筆者工作之餘才能進行開發,可投入時間不固定。截至目前(2023-02),該專案2.0版本仍未釋出,基於此未來的計劃如下:
筆者時間、能力有限,且開源專案非一朝一夕之事,存在眾多問題亦在所難免。使用、學習過程中有任何問題歡迎大家與我聯絡。
對專案有什麼想法或者建議,可以加我微信 yuyunshize 拉交流群,或者建立issues,一起完善專案