引言
(聲明:純技術部落格!)
曾幾何時,在國内還是可以通路google、faceboook、youtobe之類的網站的,後來由于防火牆的原因,導緻我們不再能夠通路這些網站了,不免為人生一大憾事!後來出于各種各樣的需求,例如查找學習資料等,就有人想要翻牆了,于是就有了翻牆代理。
原理
代理實作的關鍵在于如何繞過防火牆,得先知道防火牆是如何阻止我們通路外網的?大緻有以下三種手段:
- 域名劫持--->當你的主機發出DNS請求位址解析服務,就給你傳回一個錯誤的ip或者壓根不傳回
- IP黑名單--->國家入口網關封鎖該IP,資料無法通過
- 主幹路由器關鍵字過濾阻斷--->含有敏感關鍵字一率不允許通過
先看原理圖再解釋:
![]()
用戶端-伺服器-代理模型 過程:
用戶端負責充當一個跳闆,将浏覽器的請求資料加密(目的是讓讓資料不能被直接識别)後轉發給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:
嫌麻煩,就不注冊了。![]()
用戶端-伺服器-代理模型 遇到的問題
- server與cilent無法建立連接配接,提示驗證方法錯誤。仔細分析後發現是加密解密對應關系沒搞好,導緻server未能識别client請求。重新修改了加密和解密的位置。
- 浏覽器設定問題,client與server運作起來,但依舊無法通路外網。解決辦法就是一個字:試。幸好選項不多,多次試驗下來,搞定。設定方法在前面已經貼出。