Socks5 代理協(xié)議詳解
作者:空無
來源:SegmentFault 思否
簡介
Socks 屬于一個(gè)代理協(xié)議,可以在一些應(yīng)用層協(xié)議中間工作(比如HTTP(S),F(xiàn)TP等)。這個(gè)協(xié)議最初由David Koblas開發(fā),而后由NEC的Ying-Da Lee將其擴(kuò)展到SOCKS4。最新協(xié)議是SOCKS5,與前一版本相比,增加支持UDP、驗(yàn)證,以及IPv6。
Socks5代理協(xié)議支持多種協(xié)議,理論上應(yīng)用層協(xié)議都可以支持,比如HTTP(S)/WS(S)/SSH等
通信細(xì)節(jié)
TCP

當(dāng)客戶端與Socks5代理服務(wù)器(默認(rèn)1080端口)TCP握手完成后,會進(jìn)行一次初始化報(bào)文的發(fā)送,來確認(rèn)協(xié)議版本以及認(rèn)證方式,格式為(報(bào)文大小單位為字節(jié),長度字段皆無符號):
+----+----------+----------+|VER | NMETHODS | METHODS |+----+----------+----------+| 1 | 1 | 1 to 255 |+----+----------+----------+
VER?SOCKS版本,Socks5下是0x05 NMETHODS?METHODS部分的長度 METHODS 客戶端支持的認(rèn)證方式列表,每個(gè)方法占1字節(jié)。當(dāng)前的定義是: 0x00?不需要認(rèn)證 0x01?GSSAPI 0x02?用戶名、密碼認(rèn)證 0x03?- 0x7F由IANA分配(保留) 0x80?- 0xFE為私人方法保留 0xFF?無可接受的方法
代理服務(wù)在接受到客戶端的初始化報(bào)文后,會從METHODS中選擇一個(gè)認(rèn)證方式,并返回給客戶端:
+----+--------+|VER | METHOD |+----+--------+| 1 | 1 |+----+--------+
VER SOCKS版本,0x05; METHOD 服務(wù)端選中的方法。如果返回0xFF表示沒有一個(gè)認(rèn)證方法被選中,客戶端需要關(guān)閉連接
現(xiàn)在客戶端就可以按照約定的認(rèn)證方式來進(jìn)行認(rèn)證了,這里介紹一種“0x02 用戶名、密碼認(rèn)證”的認(rèn)證報(bào)文:
如果代理服務(wù)器返回了“0x02 用戶名、密碼認(rèn)證”的認(rèn)證方式,此時(shí)客戶端會發(fā)送認(rèn)證報(bào)文:
.------.------------------.-----------.------------------.-----------.| VER | USERNAME_LENGTH | USERNAME | PASSWORD_LNEGTH | PASSWORD |:------+------------------+-----------+------------------+-----------:| 0x01 | 1 | Variable | 1 | Variable |'------'------------------'-----------'------------------'-----------'
VER?認(rèn)證版本,默認(rèn)只有0x01 USERNAME_LENGTH 用戶名長度 USERNAME?用戶名 PASSWORD_LNEGTH?密碼長度 PASSWORD?密碼
代理服務(wù)器接收到客戶端的認(rèn)證報(bào)文后,會驗(yàn)證用戶名密碼,同時(shí)返回驗(yàn)證結(jié)果:
.------.---------.| VER | STATUS |:------+---------:| 0x01 | 1 |'------'---------'
VER?認(rèn)證版本,默認(rèn)只有0x01 STATUS 認(rèn)證結(jié)果 0x00?認(rèn)證成功 0x01?認(rèn)證失敗
認(rèn)證結(jié)束后(或者服務(wù)端選擇了不需要認(rèn)證),客戶端就會發(fā)送連接報(bào)文,報(bào)文中會包含需要連接的目標(biāo)服務(wù)地址:
+----+-----+-------+------+----------+----------+|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |+----+-----+-------+------+----------+----------+| 1 | 1 | 0x00 | 1 | Variable | 2 |+----+-----+-------+------+----------+----------+
VER 是SOCKS版本,0x05; CMD?是SOCK的命令碼 0x01?表示CONNECT請求 0x02?表示BIND請求 0x03?表示UDP轉(zhuǎn)發(fā) RSV?0x00,保留 ATYP?DST.ADDR類型 0x01?IPv4地址,DST.ADDR部分4字節(jié)長度 0x03 域名,DST.ADDR部分第一個(gè)字節(jié)為域名長度,DST.ADDR剩余的內(nèi)容為域名,沒有\(zhòng)0結(jié)尾。 0x04 IPv6地址,16個(gè)字節(jié)長度。 DST.ADDR?目標(biāo)服務(wù)地址 DST.PORT?目標(biāo)服務(wù)端口
代理服務(wù)在接收到該連接報(bào)文后,會創(chuàng)建和目標(biāo)服務(wù)器的連接,同時(shí)返回和目標(biāo)服務(wù)建立連接的結(jié)果報(bào)文:
+----+-----+-------+------+----------+----------+|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |+----+-----+-------+------+----------+----------+| 1 | 1 | 0x00 | 1 | Variable | 2 |+----+-----+-------+------+----------+----------+
VER是SOCKS版本,0x05; REP應(yīng)答字段,表示和目標(biāo)服務(wù)建立連接的結(jié)果 0x00?表示成功 0x01?普通SOCKS服務(wù)器連接失敗 0x02?現(xiàn)有規(guī)則不允許連接 0x03?網(wǎng)絡(luò)不可達(dá) 0x04?主機(jī)不可達(dá) 0x05?連接被拒 0x06?TTL超時(shí) 0x07?不支持的命令 0x08?不支持的地址類型 0x09?- 0xFF未定義 RSV?0x00,保留 ATYP?BND.ADDR類型 0x01?IPv4地址,DST.ADDR部分4字節(jié)長度 0x03 域名,DST.ADDR部分第一個(gè)字節(jié)為域名長度,DST.ADDR剩余的內(nèi)容為域名,沒有\(zhòng)0結(jié)尾。 0x04 IPv6地址,16個(gè)字節(jié)長度。 BND.ADDR?目標(biāo)服務(wù)地址 BND.PORT?目標(biāo)服務(wù)端口
至此,Socks5協(xié)議的“握手”部分完成,可以開始發(fā)送數(shù)據(jù)。代理服務(wù)器只需要將收到的客戶端數(shù)據(jù)“盲目”的轉(zhuǎn)發(fā)到目標(biāo)服務(wù),同時(shí)將收到的目標(biāo)服務(wù)數(shù)據(jù)轉(zhuǎn)發(fā)給客戶端,只是一個(gè)中繼(Relay)的角色
UDP
……
基于Netty的Socks5 代理實(shí)現(xiàn)
https://github.com/kongwu-/netty-proxy-server
參考
https://tools.ietf.org/html/rfc1928 https://zh.wikipedia.org/zh-hans/SOCKS

