一款簡單易用的內網穿透服務

咱們開發了一個內網穿透軟件Notr,整個軟件經歷了將近一年的變動,最近軟件基本穩定,用戶基本也沒在提bug了,非常欣慰。也是因爲最近處於待業狀態,有的是時間,因此將整個軟件的版本變動作一次記錄。nginx

項目起源

Notr項目的起源是我本身業餘時間寫的一個開源的項目gtun,gtun本質是一個微PN,寫gtun最主要的目的是解決兩個問題:git

  1. 方便在家裏可以訪問公司
  2. 家裏的上外網用

目前家裏一直都有在用gtun來上外網,主要是結合樹莓派作網關,因此基本上家裏全部設備都可以使用。github

至於訪問公司內網,這個是個相對比較危險的行爲,咱們小公司管理得比較鬆散因此要用的時候偶爾仍是會用的。web

gtun項目寫完一個版本以後,我才瞭解到內網穿透這個詞,可是gtun作內網穿透作得還不夠完全,我思考了下,認爲在gtun項目當中加入完善的內網穿透功能,只會讓gtun忘記了它的使命,會變得很是臃腫,因而我將這個功能獨立出來寫了一個專門解決內網穿透的項目——Notrwindows

對Notr的最初定位主要有兩點:安全

  • Notr自己提供的是內網穿透的服務,因此是一款產品
  • Notr軟件自己應該儘量保持軟件的簡潔,不用加太多花裏胡哨的東西,它最基本的使命就是讓用戶知道須要穿透本機哪一個端口就可以使用。

立足於以上兩點,咱們在gtun內網穿透功能的基礎之上,加入了動態域名解析(DDNS)以及服務註冊等功能。最終呈現給用戶的結果以下所示:服務器

使用截圖

Notr技術變動

談完了項目起源,接下來應該要談談項目具體的技術變動過程,一步一步看整個項目經歷了哪些調整。session

初始版本

初始版本很簡陋,就兩個程序,也是整個系統最小的一個模型,包括客戶端和服務端兩個,服務端有兩個功能:負載均衡

  1. 服務客戶端(驗證,session保存,IP地址分配等)
  2. 爲每個須要穿透的端口啓動一個本地端口與其對應,做爲中轉

v1.1

這一版本主要問題:ssh

  1. 首先是須要知道server的IP,端口等信息,咱們總不能告訴用戶指定哪臺服務器吧
  2. server的端口信息不固定,特別是針對http和https,公衆號調試非80和443端口用不了
  3. 用戶的驗證的key是在server節點手動指定的
  4. 用戶最後拿到的是映射到公網的IP地址

總而言之,這一版本緣由談不上產品,純粹是一個Demo,本身用徹底沒問題,可是做爲服務給別人用,顯然就拿不出手。

添加服務註冊節點的版本

爲了解決上一個版本的第一個問題,也就是IP地址和端口須要客戶端指定的問題,咱們決定開發一個接口(這一接口所在的模塊咱們稱之爲registry或者controller),讓客戶端在服務端以前,先去調用這一接口,拿到server的IP和端口信息,也就是說這一接口服務具有一個全局的視野,保存全部server節點的信息,這裏面須要考慮一個問題——registry如何知道server節點的存在以及server節點是否還在工做。

最初的解決方案是啓動的時候經過http調用registry的一個register接口,退出的時候再調用registry的unregister接口,可是有時並非說沒調unregister就說明服務在運行,因而將server和registry的通訊協議從http協議換成了tcp長連接。

爲了解決第二個問題,也就是針對http和https沒法作到端口複用,多個用戶沒法共用80和443端口,咱們開始引入了nginx,經過nginx幫咱們實現http和https的代理。這個過程很容易理解,咱們讓nginx幫咱們作反向代理了,咱們再也不本身監聽端口,nginx根據Host來作區分。

爲了解決第三個問題,咱們開始往registry模塊引入功能,這也是Notr從一個Demo轉向產品的最主要的一個步驟。咱們在registry模塊裏面加入了用戶模塊。全部用戶的註冊登陸以及key管理,都在registry模塊實現。

爲了解決第四個問題,咱們添加了一個與域名相關的模塊——DDNS,咱們DDNS的原則是:

  • 若是用戶已經註冊,那麼咱們根據用戶名信息生成一個固定的域名
  • 若是用戶沒有註冊,咱們生成一個隨機域名,讓非註冊用戶,也能體驗

這樣,不管底層server節點如何切換,對於用戶而言都是透明的,用戶感知不到,只是咱們後臺作了域名解析記錄的修改而已。

這一版本的時序圖以下所示:

v1.2

到目前爲止,這一版本基本能夠開始拿去給別人試用了,此時軟件問題開始慢慢暴露:

  • 本地的服務須要監聽0.0.0.0,由於咱們真實訪問的是本地虛擬網卡的IP地址,而不少web容器可能默認監聽的是127.0.0.1
  • windows須要安裝tap驅動,勸退了很多人
  • 須要管理員權限啓動,不少用戶安全意識很高,又勸退了一部分。

這個問題持續了好久,最後在春節放假期間進行了一次方案調整,把這些問題都完全消滅掉了。

不使用虛擬網卡的版本

在上一個版本中,全部的問題都出在方案使用了虛擬網卡構建虛擬局域網上,正是由於使用虛擬網卡,因此windows須要安裝tap驅動,也正是由於須要建立虛擬網卡,因此才須要管理員權限啓動程序。

最後咱們決定把虛擬網卡去掉,可是對外而言,幾乎沒有發生任何改變,咱們雖然消除了虛擬網卡,可是內部從server到client,依然是能夠經過虛擬IP地址進行通訊的,因此就Nginx反向代理這一層,徹底不須要作任何更改,客戶端相對上一版本而言,減小了虛擬網卡的安裝以及管理員權限,於用戶而言應該是更加方便了。

從技術細節上討論這個版本的改變,咱們關鍵的更改在於用DNAT將Nginx的反向代理流量所有導到咱們server監聽的一個tcp端口,並在內部找到這一數據流對應的客戶端,將數據轉發到客戶端上。上一版本徹底是經過路由的方式進行,這是這兩個方案最大的區別。

負載均衡策略(2019.06.11)

目前notr內網穿透服務節點均部署在中國大陸境內,最近碰到一個海外用戶問題,有個海外用戶但願使用,客戶端運行在新加坡,根據舊的負載均衡策略,會根據每一個服務節點服務的客戶端數量來選擇節點給客戶端。這裏就會有個問題:

  • 海外客戶端跟中國大陸通訊,長距離tcp丟包嚴重,延時高

根據用戶反饋,延時達到兩百多毫秒,使用ssh時有卡頓現象,不是很順暢,當時緊急開啓了一個香港節點,可是根據原來的負載均衡策略,用戶只能說有必定機率會走香港節點,並不能保證必定走。爲了解決這個問題,Notr的負載均衡策略添加一個機制:

  • 根據客戶端IP來判斷客戶端所屬區域,而後選擇該區域的服務節點

這樣保證了海外用戶連海外的節點,延時從245ms變成43ms。使用也更加順暢。

這個功能很早以前就想過添加,可是鑑於當時用戶基本都在國內,國外用戶基本沒有,基本用戶也能接受,沒有想到會有海外用戶想要使用,因此就一直沒有開發這一功能,目前該功能已經正式上線。

最後

Notr目前還有不少能夠看見的問題須要解決,可是我的精力有限,進度相對會比較慢。

前段時間有個用戶截了他的用戶信息給我,我看了下,是2018年8月份過時的,當時每一個用戶的試用期是一個月,也就是2017年7月份開始的第一個用戶,當時就很感慨,Notr已經寫了這麼久了嗎?同時也感到高興,很高興本身可以堅持作這件事作這麼久,雖然不知道結果會如何。

相關文章
相關標籤/搜索