無論是TCP還是UDP通過代理,首先要同代理取得聯繫。爲了能夠確保在第一階段順利確保數據傳輸,協議規定客戶端採用TCP方式連接聯繫代理服務器。
一旦客戶同代理的1080端口連接上,客戶首先要發送一個版本標識/方法選擇的TCP報文給代理服務器,具體格式爲:
版本號(1字節) | 可供選擇的認證方法(1字節) | 方法序列(1-255個字節長度)
如果是socks4協議,版本號就是0x04,但是這裏是支持UDP的Socks5,所以是字節0x05。此說明對於後面的報文格式解釋的版本部分也都適用。
Socks協議定義了0-255種通過代理的認證方法:
0x00 無驗證需求
0x01 通用安全服務應用程序接口(GSSAPI)
0x02 用戶名/密碼(USERNAME/PASSWORD)
0x03 至 X'7F' IANA 分配(IANA ASSIGNED)
0x80 至 X'FE' 私人方法保留(RESERVED FOR PRIVATE METHODS)
0xFF 無可接受方法(NO ACCEPTABLE METHODS)
顯然,無論是發起Socks請求的客戶端還是負責轉發Socks數據的代理都不可能完全實現所有的(起碼目前還沒有)方法,所以客戶端需要把自己能夠支持的方法列出來供代理服務器選擇。如果支持無驗證,那麼此報文的字節序列就爲:0x05 0x01 0x00,其中的0x01表示客戶端只支持一種驗證,0x00表示能夠支持的方法是編號爲0x00的(無驗證)的方法。如果客戶端還支持用戶名/密碼的驗證方式,那麼報文就應當是:0x05 0x02 0x00 0x02。
代理接收到客戶的請求,會根據自身系統的實現返回告訴客戶驗證採用哪一種方法,返回的保文格式爲:
版本號 | 服務器選定的方法
如果服務器僅支持無驗證的驗證方法,它返回字節序列:0x05 0x00。客戶端同代理的數據報文的來回應答就是Socks協議的驗證方法選擇階段。
接下來就是根據選擇的方法來,驗證客戶身份了。雖然我們這裏不需要驗證,但是還是簡單講一下0x02的用戶名/口令的驗證客戶端發送報文格式:
0x01 | 用戶名長度(1字節)| 用戶名(長度根據用戶名長度域指定) | 口令長度(1字節) | 口令(長度由口令長度域指定)
不清楚爲什麼報文的首字節是0x01(按照慣例應當是0x05)。整個報文長度根據用戶名和口令的實際長度決定。用戶名和口令都不需要以’’結束。服務器會根據提供的信息進行驗證,返回如下的報文字節序列映像爲:
0x01 | 驗證結果標誌
驗證結果標誌可以爲:0x00 驗證通過,其餘均表示有故障,不可以繼續下一步的協議步驟。
在通過了驗證步驟之後,接下來就是確定UDP傳輸的端口了。這裏面需要確定兩個重要的端口:1、客戶端發送UDP數據的本機端口,一方面可以爲發送數據指定端口,另一方面告訴代理,如果有數據返回,就傳遞給該端口,構成一個UDP傳輸迴路。2、代理想在哪個端口接收客戶發送的UDP數據報,作爲對外UDP Socket的申請方,雙方協商確定一個端口後,可以持續通過此端口向外部主機發送數據,也可以通過此端口由代理接收外部主機發回的UDP數據,再通過此端口發給UDP發送請求客戶端。客戶端會按照以下格式發送TCP數據字節序列:
協議版本 | Socks命令 | 保留字節 | 地址類型 | 特定地址 | 特定端口
Socks命令有3種:CONNECT (編號0x01) BIND (0x02) UDP(編號0x03)
保留字節長度1,爲0x00
地址類型有3種:
0X01 該地址是IPv4地址,長4個8bit字節。
0X03 該地址包含一個完全的域名。第一個8bit字節包含了後面名稱的8bit的數目,沒有中止的’’。
0X04 該地址是IPv6地址,長16個8bit字節。
特定地址一般對於多IP的主機有意義,如果不是或者不關心哪一個IP發起UDP數據傳輸,就可以填0。0。0。0,地址類型選擇0x01。比較重要的就是UDP傳輸將要從哪一個UDP端口發起。一般爲了避免因爲硬性指定一個端口導致引起衝突,會首先生成一個UDP套接字,用生成的套接字既定端口來作爲自己傳輸UDP的端口,並通過此步驟告知代理服務器。譬如臨時生成一個UDP套接字,UDP選擇端口2233作爲傳輸UDP數據的本地端口,那麼此報文就爲:0x05 0x03 0x00 0x00 0x00 0x00 0x00 0x08 0xb9 其中0x08 0xb9換算成10進制就是2233。
代理服務器會根據自己的端口占用情況,給出一個有關代理服務器的端口的回覆字節序列,告訴客戶可以將UDP數據發送到此地址和端口中去,以實現UDP穿透代理。返回的字節序列爲:
版本 | 代理的應答 | 保留1字節 | 地址類型 | 代理服務器地址 | 綁定的代理端口
代理的應答可以爲值:
0X00 成功協商
0X01 常見的Socks故障
0x02 不允許連接
0X03 網絡不可到達
0X04 主機不可到達
0X05 連接被重置
0X06 TTL 失效
0X07 命令不支持
0X08 地址類型不支持
0X09 一直到0xff都保留
代理的地址指客戶端需要發給那一個IP,綁定的端口指代理將在哪一個端口上爲客戶接收數據並轉發出去。地址類型、地址參照上面的解釋。
通過以上的TCP協商幾個步驟後,現在客戶端明確了自己將需要發送的UDP數據發給代理服務器的某個IP的某個端口了。代理服務器也知道是哪一個IP發送數據報給自己,如果接收到由於轉發此UDP數據報而從遠端目標主機傳回的數據報,他需要根據協議將收到的數據報返回給客戶的特定端口。此特定端口就是此步驟中字節序列中綁定的代理端口
在傳輸UDP數據時,由於通過代理,所以需要按照一定的格式進行包裝,在需要傳送的數據之前添加一個報頭,具體爲:
保留2字節的0 | 是否數據報分段重組標誌 | 地址類型 | 將要發到代理外的目標地址 | 遠端目標主機的端口 | 需要通過代理傳送出去的數據
是否數據報分段重組標誌爲0表示該數據報文是獨立的不需要重新組合,其他的表示特定的序列號,以利於UDP報文整合。
這裏的地址是最終接收此UDP數據的代理外的服務器地址,我們這個例子中就是192。168。0。250。端口就是8100。根據地址類型
例子: