由淺入深寫代理(3) -socks5 代理
本文講的是如何寫一個 socks5 代理,其實 shadowsocks 的代理也是 socks5 協議的,所以 socks5 代理也是本系列教程的一個重點。
首先放出 socks5 協議的 [rfc](https://www.ietf.org/rfc/rfc1928.txt),socks5 協議很簡單,SOCKS5 協議並不負責代理伺服器的數據傳輸環節,此協議只是在 C/S 兩端真實交互之間,建立起一條從客戶端到代理伺服器的授信連接。
0x01 sock5 代理結構圖
0x02 socks5 協議分析
認證階段
首先客戶端需要和服務端有個握手認證的過程,可以採用 用戶名/密碼 認證或者無需認證方式。
格式如下 (數字表示位數)
+----+----------+----------+n |VER | NMETHODS | METHODS |n +----+----------+----------+n | 1 | 1 | 1~255 |n +----+----------+----------+n
- VER 欄位是當前協議的版本號,也就是 5;
- NMETHODS 欄位是 METHODS 欄位佔用的位元組數;
- METHODS 欄位的每一個位元組表示一種認證方式,表示客戶端支持的全部認證方式。
0x00: NO AUTHENTICATION REQUIREDn 0x01: GSSAPIn 0x02: USERNAME/PASSWORDn 0x03: to X』7F』 IANA ASSIGNEDn 0x80: to X』FE』 RESERVED FOR PRIVATE METHODSn 0xFF: NO ACCEPTABLE METHODSn
服務端返回格式
+----+--------+n |VER | METHOD |n +----+--------+n | 1 | 1 |n +----+--------+n
一般情況下服務端返回兩種情況
0x05 0x00:告訴客戶端採用無認證的方式建立連接;
0x05 0xff:客戶端的任意一種認證方式伺服器都不支持。
舉個例子, 伺服器無需認證的情況如下
client -> server: 0x05 0x01 0x00n server -> client: 0x05 0x00n
連接階段
認證完成,客戶端向服務端發送請求:
+----+-----+-------+------+----------+----------+n |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |n +----+-----+-------+------+----------+----------+n | 1 | 1 | 1 | 1 | Variable | 2 |n +----+-----+-------+------+----------+----------+n
- CMD 欄位 command 的縮寫:
* 0x01:CONNECT 建立 TCP 連接n * 0x02: BIND 上報反向連接地址n * 0x03:關聯 UDP 請求n
- RSV 欄位:保留欄位,值為 0x00
- ATYP 欄位:address type 的縮寫,取值為:
* 0x01:IPv4 n * 0x03:域名n * 0x04:IPv6n
- DST.ADDR 欄位:destination address 的縮寫,取值隨 ATYP 變化:
* ATYP == 0x01:4 個位元組的 IPv4 地址n * ATYP == 0x03:1 個位元組表示域名長度,緊隨其後的是對應的域名n * ATYP == 0x04:16 個位元組的 IPv6 地址n * DST.PORT 欄位:目的伺服器的埠n
服務端返回格式
+----+-----+-------+------+----------+----------+n |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |n +----+-----+-------+------+----------+----------+n | 1 | 1 | 1 | 1 | Variable | 2 |n +----+-----+-------+------+----------+----------+n
- REP 欄位
* X00 succeededn * X01 general SOCKS server failuren * X02 connection not allowed by rulesetn * X03 Network unreachablen * X04 Host unreachablen * X05 Connection refusedn * X06 TTL expiredn * X07 Command not supportedn * X08 Address type not supportedn * X09 to XFF unassignedn
舉個例子,客戶端通過 127.0.0.1:8000 的代理髮送請求
# request: VER CMD RSV ATYP DST.ADDR DST.PORTn client -> server: 0x05 0x01 0x00 0x01 0x7f 0x00 0x00 0x01 0x1f 0x40n # response: VER REP RSV ATYP BND.ADDR BND.PORTn server -> client: 0x05 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x10 0x10n
傳輸階段
接下來就開始傳輸數據,socks5 伺服器只做單純的轉發功能
整個過程如下
# 認證階段n client -> server: 0x05 0x01 0x00n server -> client: 0x05 0x00n # 連接階段n client -> server: 0x05 0x01 0x00 0x03 0x0a bgoogle.com 0x00 0x50n server -> client: 0x05 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x10 0x10n # 傳輸階段n client -> server -> remoten remote -> server -> clientn ... n
下篇教程用代碼實現下 socks5 代理
參考鏈接:
* Shadowsocks 源碼分析--協議與結構
* https://www.ietf.org/rfc/rfc1928.txt
* SOCKS5 協議解析 - 莫邪
推薦閱讀:
※Python數據分析及可視化實例之文本處理文本相似度(29)
※玩點好玩的--知乎全部話題關係可視化(Docker+Flask+Bootstrap+echarts+uWSGI+Nginx)
※Python安全工具開發(一) :分散式爬蟲初探