天天看點

用戶端-伺服器-代理模型

引言

(聲明:純技術部落格!)

曾幾何時,在國内還是可以通路google、faceboook、youtobe之類的網站的,後來由于防火牆的原因,導緻我們不再能夠通路這些網站了,不免為人生一大憾事!後來出于各種各樣的需求,例如查找學習資料等,就有人想要翻牆了,于是就有了翻牆代理。

原理

代理實作的關鍵在于如何繞過防火牆,得先知道防火牆是如何阻止我們通路外網的?大緻有以下三種手段:
  1. 域名劫持--->當你的主機發出DNS請求位址解析服務,就給你傳回一個錯誤的ip或者壓根不傳回
  2. IP黑名單--->國家入口網關封鎖該IP,資料無法通過
  3. 主幹路由器關鍵字過濾阻斷--->含有敏感關鍵字一率不允許通過

先看原理圖再解釋:

用戶端-伺服器-代理模型

過程:

用戶端負責充當一個跳闆,将浏覽器的請求資料加密(目的是讓讓資料不能被直接識别)後轉發給server。由于資料經過了加密,是以也就不會被主幹路由器的關鍵字屏蔽技術阻擋。我們直接讓client與server溝通,是以用不到DNS服務,也就不會存在被假的IP欺騙或是找不到IP位址的情況。又因為我們會給server選擇一個不知名的IP位址,即不會是防火牆IP黑名單中的位址,是以不會被封鎖。(跨出國門第一步)

server接收到來自client的資料,先解密,然後代理浏覽器發出請給對應網站伺服器。網站伺服器将server請求的資料再傳給它,server再将資料進行加密,發送給我們的client。

最後,client将解密後的資料交給浏覽器,這便是大緻的原理了。

SOCKS5協定:

SOCKS5 是一個代理協定,它在使用TCP/IP協定通訊的前端機器和伺服器機器之間扮演一個中介角色,使得内部網中的前端機器變得能夠通路Internet網中的伺服器,或者使通訊更加安全。SOCKS5 伺服器通過将前端發來的請求轉發給真正的目标伺服器, 模拟了一個前端的行為。在這裡,前端和SOCKS5之間也是通過TCP/IP協定進行通訊,前端将原本要發送給真正伺服器的請求發送給SOCKS5伺服器,然後SOCKS5伺服器将請求轉發給真正的伺服器。

我們這裡也要借助這個協定,讓我們的資料通過防火牆。下面列出相關的知識。

RFC1928(URL為:http://www.ietf.org/rfc/rfc1928.txt)描述了Socks協定的細節,告訴我們客戶程式如何同Socks代理協商,取得透過該協定對外傳輸的途徑。看了看RFC1928文檔,大概整理出了socks5伺服器處理TCP請求的流程:

socks5連接配接建立的時候首先由用戶端發出如下格式資料給服務端:

用戶端-伺服器-代理模型

在SOCKS5中VER位元組總是0x05代表socks5,NMETHODS存放用戶端可以接受的認證方法數量n,後面的n個位元組就是各個方法對應的編号了。

收到用戶端發出的請求後,服務端做出回應:

用戶端-伺服器-代理模型

其中驗證方法對應的編号如下:

          o  X'00' NO AUTHENTICATION REQUIRED

          o  X'01' GSSAPI

          o  X'02' USERNAME/PASSWORD

          o  X'03' to X'7F' IANA ASSIGNED

          o  X'80' to X'FE' RESERVED FOR PRIVATE METHODS

          o  X'FF' NO ACCEPTABLE METHODS

用戶端接受到如此回應後就可以開始與服務端進行驗證了。在此0x02号代表的使用者名密碼驗證方式在RFC1929文檔中有介紹。我先不管驗證,先實作匿名socks5代理。以後再考慮添加驗證功能。

驗證完畢後,用戶端就可以開始提出要求了。到底要socks5代理為它做什麼。請求資料包的格式如下:

用戶端-伺服器-代理模型

各位元組代表的意義:

          o  VER    protocol version: X'05'

          o  CMD

             o  CONNECT X'01'

             o  BIND X'02'

             o  UDP ASSOCIATE X'03'

          o  RSV    RESERVED

          o  ATYP   address type of following address

             o  IP V4 address: X'01'

             o  DOMAINNAME: X'03'

             o  IP V6 address: X'04'

          o  DST.ADDR       desired destination address

          o  DST.PORT desired destination port in network octet order

這裡的目标位址可以有三種格式(IPV4 IP,域名,IPV6 IP)。其中IPV4,IPV6位址固定長度分别為4位元組,16位元組。域名以pascal字元串儲存:第一位元組為字元串長度,後面跟字元串内容。

收到用戶端的請求後,服務端開始回應:

用戶端-伺服器-代理模型

 Where:

          o  VER    protocol version: X'05'

          o  REP    Reply field:

             o  X'00' succeeded

             o  X'01' general SOCKS server failure

             o  X'02' connection not allowed by ruleset

             o  X'03' Network unreachable

             o  X'04' Host unreachable

             o  X'05' Connection refused

             o  X'06' TTL expired

             o  X'07' Command not supported

             o  X'08' Address type not supported

             o  X'09' to X'FF' unassigned

          o  RSV    RESERVED

          o  ATYP   address type of following address

             o  IP V4 address: X'01'

             o  DOMAINNAME: X'03'

             o  IP V6 address: X'04'

          o  BND.ADDR       server bound address

          o  BND.PORT       server bound port in network octet order

   Fields marked RESERVED (RSV) must be set to X'00'.

對應用戶端的3種不同要求:

針對CONNECT請求的回複:

BND.PORT裡面儲存的是服務端連接配接到遠端伺服器所配置設定的端口,BND.ADDR儲存的是配置設定的IP位址。(這裡socks5為什麼這麼做我還有點不清楚,不過不管它,先實作再說,以後在看看socks5 proxy client那邊是怎麼利用的)

針對BIND請求的回複:

    服務端将兩次回複用戶端。第一次回複是在服務端開啟新的socket并開啟一個端口偵聽後。BND.PORT存放服務端偵聽的端口。BND.ADDR存放IP位址。用戶端一般會利用這段資訊來告訴遠端伺服器。第二次回複是用來表明遠端伺服器連接配接成功。BND.PORT和BND.ADDR分别存放遠端伺服器連接配接用的端口及IP。

源碼

源碼挺長的,就不貼出來了,托管在GitHub上,附上連結:https://github.com/Fireplusplus/Project/tree/master/esocks

啟動步驟

(費盡心思從别人那裡借來的伺服器的賬号,當然你也可以自己買一個:網址:https://www.linode.com/ 就是有點小貴,一個月大概60~70RMB)

首先,得把server部署到伺服器上:

               scp server  [email protected]:/dir --->          将伺服器應用程式拷到遠端伺服器上

               ssh [email protected]                 --->          登入到伺服器

               ./ser 6666                               --->          将伺服器跑起來(6666就是client與server通信的端口,不沖突即可)

啟動用戶端:

              ./cli 6667 IP 6666                     --->          第一個端口号為client與浏覽器通信端口,後邊接伺服器IP和端口号

最後,設定浏覽器資訊(以FireFox浏覽器為例):

選項--->進階--->網絡--->設定:

用戶端-伺服器-代理模型

運作結果

現在就可以通路外網啦!

熟悉的界面又回來了

用戶端-伺服器-代理模型
用戶端-伺服器-代理模型
上youtobe看個小視訊
用戶端-伺服器-代理模型
用戶端-伺服器-代理模型
用戶端-伺服器-代理模型

畫質清晰,視訊流暢,nice!

上個Twitter:

用戶端-伺服器-代理模型

國外的微網誌,不錯呦!

再來個Facebook:

用戶端-伺服器-代理模型
嫌麻煩,就不注冊了。

遇到的問題

  1. server與cilent無法建立連接配接,提示驗證方法錯誤。仔細分析後發現是加密解密對應關系沒搞好,導緻server未能識别client請求。重新修改了加密和解密的位置。
  2. 浏覽器設定問題,client與server運作起來,但依舊無法通路外網。解決辦法就是一個字:試。幸好選項不多,多次試驗下來,搞定。設定方法在前面已經貼出。

繼續閱讀