程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#實現Socket5代理協議通訊

C#實現Socket5代理協議通訊

編輯:關於C#

這裡主要講的是用.NET實現基於Socket5下面的代理協議進行客戶端的通訊,Socket4的實現是類似的,注意的事,這裡不是講用C#實現一個代理服務器,因為實現一個代理服務器需要實現很多協議,頭大,而且現在市面上有很多現成的代理服務器用,性能又好,直接用不好嗎?而是用C#來實現客戶端通過一個代理服務器進行Socket5的通訊,這個簡單點,一般來說用Socket5就好了,Socket4現在也逐漸淘汰,基本上代理服務器都支持Socket5。

首先我們要了解下Socket5的代理協議是基於TCP協議之上的,從Socket4擴展上來的,用於提供給其他協議例如HTTP、FTP所作用的一套防火牆協議。

(這裡做點小解釋,實際上應該是SOCKS V5協議,但是目前網上都用Socket5這樣稱呼,目前本文也暫時這樣稱)

然後下面簡單的說下該協議的內容,具體分為兩部分:

一部分是基於TCP協議的客戶

當一個基於TCP協議的客戶端希望與一個只能通過防火牆可以到達的目標(這是由實現所決定的)建立連接,它必須先建立一個與SOCKS服務器上SOCKS 端口的TCP連接。通常這個TCP端口是1080。當連接建立後,客戶端進入協議的“握手(negotiation)”過程:認證方式的選擇,根據選中的方式進行認證,然後發送轉發的要求。SOCKS服務器檢查這個要求,根據結果,或建立合適的連接,或拒絕。是不是有點像FTP?差不多。

握手的過程:

客戶端連到服務器後,然後就發送請求來協商版本和認證方法:

VER NMETHODS METHODS 1 1 1 to 255

這個版本的SOCKS協議中,VER字段被設置成X'05'。NMETHODS字段包含了在METHODS字段中出現的方法標示的數目(以字節為單位)。簡化就是像服務器發送05 01 00

服務器從這些給定的方法中選擇一個並發送一個方法選中的消息回客戶端:

VER METHOD 1 1

如果選中的消息是X’FF’,這表示客戶端所列出的方法列表中沒有一個方法被選中,客戶端必須關閉連接。

這裡我們關注的是 X’00’ 不需要認證和X’02’ 用戶名/密碼,簡化是服務器會返回的前兩個字節

會是05 00或者05 02,02的時候進行驗證。

驗證過程結束後,客戶端就發送詳細的請求信息。如果協商的方法中有以完整性檢查和/或安全性為目的的封裝,這些請求必須按照該方法所定義的方式進行封裝。

握手完成之後,要進行一個請求連接,這個就是對遠程服務器的連接,我們知道當前既然連接的是代理服務器,我們實際上發送數據的對象並不是它,也就是我們要告訴代理服務器去連接真實的某某,現在就是在做這一步了。

SOCKS請求的格式如下:

VER CMD RSV ATYP DST.ADDR DST.PROT 1 1 X’00’ 1 Variable 2

其中

· VER 協議版本: X’05’

· CMD

· CONNECT:X’01’

· BIND:X’02’

· UDP ASSOCIATE:X’03’

· RSV 保留

· ATYP 後面的地址類型

· IPV4:X’01’

· 域名:X’03’

· IPV6:X’04’'

· DST.ADDR 目的地址

· DST.PORT 以網絡字節順序出現的端口號

SOCKS服務器會根據源地址和目的地址來分析請求,然後根據請求類型返回一個或多個應答。

ATYP字段中描述了地址字段(DST.ADDR,BND.ADDR)所包含的地址類型:

· X'01'

基於IPV4的IP地址,4個字節長

· X'03'

基於域名的地址,地址字段中的第一字節是以字節為單位的該域名的長度,沒有結尾的NUL字節。

· X'04'

基於IPV6的IP地址,16個字節長。

Variable表示該域的長度是可變的。

以最常用的IP表示法為例,加入我們的代理服務器地址是10.10.1.254,現在我們要通過代理服務器訪問192.168.1.2這個IP地址,這裡不要看做局域網地址,因為是通過代理進行訪問的,

前期傳遞了IP對象IPEndPoint destIP;

byte [] data = new byte[10];

data[0]=5;data[1]=1;data[2]=0;data[3]=1;//前4個字節

Array.Copy(destIP.Address.GetAddressBytes(), 0, data, 4, 4); //IP地址

Array.Copy(BitConverter.GetBytes(

IPAddress.HostToNetworkOrder(destIP.Port)), 2, data, 8, 2); //端口號

這個data就是要發送的請求了.

代理服務器這邊會根據請求,以如下格式返回:

VER REP RSV ATYP BND.ADDR BND.PORT 1 1 X’00’ 1 Variable 2

其中:

· VER 協議版本: X’05’

· REP 應答字段:

· X’00’ 成功

· X’01’ 普通的SOCKS服務器請求失敗

· X’02’ 現有的規則不允許的連接

· X’03’ 網絡不可達

· X’04’ 主機不可達

· X’05’ 連接被拒

· X’06’ TTL超時

· X’07’ 不支持的命令

· X’08’ 不支持的地址類型

· X’09’ – X’FF’ 未定義

· RSV 保留

· ATYP 後面的地址類型

· IPV4:X’01’

· 域名:X’03’

· IPV6:X’04’

· BND.ADDR 服務器綁定的地址

· BND.PORT 以網絡字節順序表示的服務器綁定的段口

標識為RSV的字段必須設為X’00’。

返回的信息裡面都看到,最重要是第二個域,如果為0,就表示成功,這第二個域對於接收到bytes來說是第1個字節,及data[1].

如果選中的方法中有以完整性檢查和/或安全性為目的的封裝,這些應答必須按照該方法所定義的方式進行封裝。

完成這步請求就完成了Socket5整個TCP客戶端的連接了,剩下的工作,你就如正常的連接一下向代理服務器發送數據,簡單來說這時候你就把代理服務器看成遠程你要連接的對象就行了,代理服務器此時就是個透明的網絡連接。至於整個C#示例,可以到我的空間下載,這個是博客園文件下載鏈接。

對於UDP的客戶端連接,這裡給出協議規范,可以自行進行實驗。

在UDP ASSOCIATE應答中由BND.PORT指明了服務器所使用的UDP端口,一個基於UDP協議的客戶必須發送數據報至UDP轉發服務器的該端口上。如果協商的認證方法中有以完整性、認證和/或安全性為目的的封裝,這些數據報必須按照該方法所定義的方式進行封裝。每個UDP數據報都有一個UDP請求頭在其首部:

RSV FRAG ATYP DST.ADDR DST.PORT DATA 2 1 1 Variable 2 Variable

在UDP請求頭中的字段是:

· RSV 保留 X’0000’

· FRAG 當前的分段號

· ATYP 後面的地址類型

· IPV4:X’01’

· 域名:X’03’

· IPV6:X’04’

· DST.ADDR 目的地址

· DST.PORT 以網絡字節順序出現的端口號

· DATA 用戶數據

當一個UDP轉發服務器轉發一個UDP數據報時,不會發送任何通知給客戶端;同樣,它也將丟棄任何它不能發至遠端主機的數據報。當UDP轉發服務器從遠端服務器收到一個應答的數據報時,必須加上上述UDP請求頭,並對數據報進行封裝。

UDP轉發服務器必須從SOCKS服務器得到期望的客戶端IP地址,並將數據報發送到UDP ASSOCIATE應答中給定的端口號。如果數據報從任何IP地址到來,而該IP地址與該特定連接中指定的IP地址不同,那麼該數據報會被丟棄。

FRAG字段指明數據報是否是一些分片中的一片。如果SOCKS服務器要實現這個功能,X’00’指明數據報是獨立的;其他則越大越是數據報的尾端。介於 1到127之間的值說明了該分片在分片序列裡的位置。每個接收者都為這些分片提供一個重組隊列和一個重組的計時器。這個重組隊列必須在重組計時器超時後重新初始化,並丟棄相應的數據報。或者當一個新到達的數據報有一個比當前在處理的數據報序列中最大的FRAG值要小時,也必須重新初始化從組隊列。重組計時器必須小於5秒。只要有可能,應用程序最好不要使用分片。

分片的實現是可選的;如果某實現不支持分片,所有FRAG字段不為0的數據報都必須被丟棄。

一個SOCKS的UDP編程界面(The programming interface for a SOCKS-aware UDP)必須報告當前可用UDP數據報緩存空間小於操作系統提供的實際空間。

· 如果 ATYP是 X’01’ - 10+method_dependent octets smaller

· 如果 ATYP是X’03’ - 262+method_dependent octets smaller

· 如果 ATYP是X’04’ - 20+method_dependent octets smaller

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved