BadVPN詳解之--始記:透明socks代理與tun2socks

龍蝦天天發表於2017-05-15
上週六晚上閒來無事跟以前的同事聊天,問之最近有沒有接觸到什麼比較好玩的技術,答曰tun2socks。這個正合我的胃口,我所謂的好玩的技術是那種簡單,有用的技術點或者技術框架,能在10分鐘內領略其原理和思想,能在20分鐘內跑起來,能在半天內徹底剖析它的結構,能在此後很久的時間受益無窮。OpenVPN就是這樣的“好玩”的東西,網路卡點燈也算,tun2socks是另一個,當然還有一個更好玩的,那就是BadVPN,我要在另外的文章中單獨介紹。本文先來介紹tun2socks,它其實是BadVPN的一個組成部分。
       能玩tun2socks,要特別感謝這位目前貌似已經穿上皮鞋的劉經理,在我離職後搶了我最後面的經理工位,卻放棄了我那把尊貴的防爆炸座椅(指不能旋轉升降的座椅,因為旋轉升降座椅會爆炸)。

總覽

tun2socks實現一種機制,它可以讓你無需改動任何應用程式而完全透明地將資料用socks協議封裝,轉發給一個socks代理,然後由該代理程式負責與真實伺服器之間轉發應用資料。使用代理有兩種方式,一種是你自己顯式配置代理,這樣一來,資料離開你的主機時它的目標地址就是代理伺服器,另一種是做透明代理,即在中途把原始資料重定向到一個應用程式,由該代理程式代理轉發。tun2socks在第二種的基礎上,完成了socks協議的封裝,並且實現該機制時使用了強大的tun網路卡而不必再去配置複雜的iptables規則。

什麼是socks代理

本文以TCP為例,就不再提UDP了。所以說,簡單點,把socks代理稱為帶有認證功能的TCP代理是合適的。
       TCP代理非常容易理解,然而純粹的TCP代理並不實用,必然要加入一些控制功能,比如誰可以被代理,誰不能被代理,如何認證,最多可以代理多少路的請求等等。有了這些控制手段,TCP代理才真正變得實用起來。

附:socks代理如何運作

socks的運作原理非常簡單,就是在TCP資料外包一層socks協議頭,到達socks代理伺服器後,脫去socks頭,然後通過socks伺服器與真實伺服器之間建立的連線將TCP裸資料傳給真實伺服器。如下圖所示:

請注意,socks代理並不理解任何應用層協議,它只是負責轉發應用層資料而已,這一點使socks成為了一個通用的代理協議,這一點和HTTP代理伺服器是完全不同的。

什麼是tun網路卡

這個就不再多說。之所以有這個小節是為了文章的完整性。也是為了給初學者一個完整的提綱來更深入的學習。

什麼是透明代理

我理解的透明代理就是“偷偷的給你做代理”,這一點與你在瀏覽器裡顯式設定socks代理伺服器完全不同。透明代理就比如說下面這樣子:

要實現這一點有很多方式,比如你可以用Linux的TProxy+Policy routing機制,關於這種方式請參見《socket的IP_TRANSPARENT選項實現代理》,然而,很多時候,這種方式行不通。

現實中的需求

如果給一個Linux的root賬戶,那麼幾乎可以隨意顯擺,而很多時候這並不可能。比如Android系統就不能隨意root,這就意味著你無法在Android系統上隨意地配置iptables規則,路由等。那麼想在Android系統上免root實現一個透明代理,就需要別的辦法。而tun2socks提供了一種這樣的辦法。

tun2socks能做什麼

如果理解了上述所有的概念,那麼tun2socks就不剩下什麼了。先給出一個總覽圖:

通過上圖,我們看到tun2socks可以被拆解出三個部分,即tun網路卡部分,協議處理部分以及socks轉換部分,這三部分在tun2socks的處理流程是序列的。我來一個一個說。

1.tun網路卡部分

該部分解決了一個基本的問題,即“如何獲取原始的資料包”。拿到了資料包,什麼都好辦了。

2.協議處理部分

如果你想做透明代理,那麼你必須“想辦法把資料流匯入到本地”,完成這件事有好多種辦法,以Linux為例,比如做一個DNAT即可完成,再比如如上所述,用tun網路卡直接把原始資料包捕獲到一個應用程式。顯然tun2socks採用了後者。
       兩者有何不同呢?
       很大的不同。如果使用DNAT的話,目標地址和埠將會是本地的一個代理程式,比如socks代理,那麼作業系統的協議棧會自動將資料包交到該代理程式,除了這個DNAT之外不需要再做任何操作。而使用tun捕獲資料包的話,由於只是捕獲到了IP資料包文,這意味著你要自己處理IP層以上的邏輯,比如TCP按序交付,TCP狀態處理,TCP擁塞控制,你要確保代理程式收到的資料包看起來是“經過協議棧處理過的資料包”,“就像是直接從socket的recv介面讀到的一樣”。
       tun2socks使用現成的lwip來完成了協議處理。lwip是一個輕量級的使用者態協議棧,非常適合完成這種協議適配工作。

附:Android系統使用TAP模式的tun網路卡

說起lwip來處理tun捕獲的原始IP資料包文與socks協議的適配工作,我想起了很早之前我也做過同樣的事情。那就是在Android系統上使用TAP模式的tun網路卡。


3.socks協議轉換部分

經過第2部分,即協議處理之後,現在tun2socks拿到的已經是源主機試圖傳送到原始目標主機的裸資料了,接下來它可以做的事情可就多了,當然可以用socks協議封裝裸資料,將其傳送給一個socks代理程式。


tun2socks與OpenVPN

只要是使用了tun網路卡獲取原始資料,那麼任何框架都會面臨一個必須回答的問題,即拿到原始的IP資料包文或者以太幀之後,下一步如何處理這些資料。OpenVPN和tun2socks顯然是給出了兩種不同的回答,而這不同的回答即是OpenVPN和tun2socks之間唯一的不同。

後記

這篇文章的最初內容來自於劉經理,我只是做了補充。然而沿著這個tun2socks一路走下去,我發現了一個十分好玩的東西,那就是BadVPN,所以我準備寫一篇關於BadVPN的文章了,請注意接收。



相關文章