以前編寫的一個基於openfire服務器的即時通信軟件,由於部署環境須要,須要增長代理登陸通訊的實現。整理了一下相關代理的知識分享一下。安全
一個基於TCP協議的客戶端但願與一個只能經過特定網絡節點才能夠聯通的目標創建通信時,它必須在該節點搭建代理,先創建一個與SOCKS服務器上端口的TCP鏈接(TCP端口能夠是1080)。當鏈接創建後,客戶端和代理服務器進入協議的「握手(negotiation)」過程,握手經過事後,這時就創建了客戶端和代理之間的鏈接。完成握手後代理能夠看做一個透明的網絡,向代理髮送真正的請求協議便可實現代理請求。服務器
整個代理過程主要分兩個重要的階段「協議握手」、「代理請求」,代理請求由代理服務器上的代理服務處理,如今有不少成熟的代理軟件,選一個便可。咱們主要實現的是基於代理軟件的鏈接,或者說是實現基於SOCKS V5協議的鏈接過程(應用是代理IM的通訊),因此主要實踐「協議握手(negotiation)」。網絡
協議握手的過程:併發
客戶端連到服務器後,而後就發送請求來協商版本和認證方法〔格式見下〕:spa
VER代理 |
NMETHODSci |
METHODS部署 |
1域名 |
1io |
1 to 255 |
SOCKS v5協議中,VER字段被設置成X'05'。NMETHODS字段包含了在METHODS字段中出現的方法標示的數目(以字節爲單位)。 咱們發送請求商定版本和認證方式後(發送05 01 00),服務器從給定的方法中選擇一個併發送一個方法選中的消息回客戶端〔格式見下〕
VER |
METHOD |
1 |
1 |
返回的消息中若是是X’FF’,這表示客戶端所列出的方法列表中沒有一個方法被選中,客戶端必須關閉鏈接。咱們須要關注的第二位的消息內容,返回的消息是05 00或者05 02(00 忽略驗證 ;02 進行用戶驗證)。
下面咱們要了解的則是「0x02 用戶名/密碼」驗證的過程。
當客戶端發送帶有0x02認證方法的報文(如:「0x05 0x01 0x02」)到服務端時,根據報文,服務端得知客戶端支持用戶名/密碼認證(0x02),所以若是服務端須要驗證,則發送「0x05 0x02」應答,這樣客戶端將會進入「用戶名/密碼」驗證過程。
「0x02 用戶名/密碼」驗證協議的報文格式是:
0x01 | 用戶名長度(1字節)| 用戶名(長度根據用戶名長度域指定) | 口令長度(1字節) | 口令(長度由口令長度域指定)
因此報文的長度是根據用戶名與密碼的長度而定,好比如下報文:
0x01 0x02 0x41 0x42 0x02 0x43 0x43
則表示發送用戶名爲「AB」密碼爲「CC」的驗證報文。
服務端接收到用戶名/密碼驗證報文後進行相應處理並返回如下格式的應答報文:
0x01 | 驗證結果標誌
驗證過程結束後,客戶端就發送詳細的請求信息。若是協商的方法中有以完整性檢查和/或安全性爲目的的封裝,這些請求必須按照該方法所定義的方式進行封裝。
協議握手完成以後,就須要發送一個請求鏈接,這個鏈接便是對遠程服務器的鏈接,由於如今咱們直連的是代理服務器,因此須要告訴代理服務器,咱們要鏈接xxx地址。
請求的格式以下:
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 以網絡字節順序出現的端口號
ATYP字段中描述了地址字段(DST.ADDR,BND.ADDR)所包含的地址類型:
X'01':基於IPV4的IP地址,4個字節長;
X'03':基於域名的地址,地址字段中的第一字節是以字節爲單位的該域名的長度,沒有結尾的NUL字節;·
X'04':基於IPV6的IP地址,16個字節長。
Variable:表示該域的長度是可變的。
代理服務器這邊會根據請求內容返回特定格式的消息(以下格式)。
VER |
REP |
RSV |
ATYP |
BND.ADDR |
BND.PORT |
1 |
1 |
X’00’ |
1 |
Variable |
2 |
注:標識爲RSV的字段必須設爲X’00’。
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 以網絡字節順序表示的服務器綁定的段口
返回的信息裏面都看到,返回結果在第二個域,爲0則表示成功。
驗證請求成功後,Socket5整個TCP客戶端的鏈接就完成了。這時候代理服務器就能夠看做是一個透明的網絡鏈接。