Socks5协议简介
socks5协议是一种代理协议,用于在客户端与服务器直接转发数据。
简单来说,一般适用于如下场景,若Client无法访问目标服务器,但能访问socks5代理服务器,而socks5服务器能够访问目标服务器,那么Client就可以通过socks5代理服务器访问目标服务器。
socks5协议的具体RFC1928文档如下
https://www.ietf.org/rfc/rfc1928.txt
工作过程
无代理情况下
1 | @startuml |
有代理情况下
1 | @startuml |
代理服务器实现
接受客户端的TCP连接
1 | func main() { |
当TCP连接建立完成后,对于每个Client的处理流程在每个goroutine中,
1 | func process(conn net.Conn) { |
协商阶段
首先客户端向socks5代理服务器发送请求,其中包含了可用的鉴权方式,内容如下,
Field | VER | NMETHODS | METHODS |
---|---|---|---|
Length | 1 | 1 | 1 to 255 |
VER: 协议版本socks5为0x05
NMETHODS: 支持的认证方法数
METHODS: 有NMETHODS个字节,其中包含了各种认证方式
-
0x00: NO AUTHENTICATION REQUIRED
无需验证
-
0x01: GSSAPI
通用安全服务应用程序接口
-
0x02: USERNAME/PASSWORD
用户名密码
-
0x03 to 0x7F: IANA ASSIGNED
一般不用。INNA保留
-
0x80 to 0xFE: RESERVED FOR PRIVATE METHODS
保留作私有用处
-
0xFF: NO ACCEPTABLE METHODS
不接受任何方法/没有合适的方法
1 | const Socks5Version = 0x05 |
然后服务器选中一个支持的METHOD返回给客户端,格式如下
Field | VER | METHOD |
---|---|---|
Length | 1 | 1 |
当客户端收到的METHOD字段值为0x00时,直接跳过认证阶段进入请求阶段,当收到0xFF时,直接断开连接,其他的值则进入相应的认证阶段。
1 | func sendSupportedMethod(method byte, conn net.Conn) (err error) { |
最后,协商阶段的函数为
1 | func auth(reader *bufio.Reader, conn net.Conn) error { |
请求阶段
协商完毕后,客户端向socks5服务器发起请求,格式如下,
Field | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
---|---|---|---|---|---|---|
Length | 1 | 1 | 0x00 | 1 | Variable | 2 |
-
VER: 协议版本,0x05
-
CMD: 控制字,表示要干啥
-
0x01: CONNECT连接
-
0x02: 端口监听
-
0x03: 使用UDP
-
-
RSV: 保留位0x00
-
ATYP: address type 目标地址类型
-
0x01: IPv4
-
0x03: 域名
-
0x04: IPv6
-
-
DST.ADDR: 目标地址值
-
若IPv4则有四字节
-
若IPv6则有16字节
-
若为域名,则第一个字节为字符串长度,接下来有第一个字节这么大的目标地址
-
-
DST.PORT: 目标端口号
之后socks5向客户端返回如下信息
Field | VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
---|---|---|---|---|---|---|
Length | 1 | 1 | 0x00 | 1 | Variable | 2 |
o VER protocol version: X'05'
o REP Reply field:
o X'00' succeeded
o X'01' general SOCKS server failure
o X'02' connection not allowed by ruleset
o X'03' Network unreachable
o X'04' Host unreachable
o X'05' Connection refused
o X'06' TTL expired
o X'07' Command not supported
o X'08' Address type not supported
o X'09' to X'FF' unassigned
o RSV RESERVED
o ATYP address type of following address
1 | package main |
所有常量定义
1 | package main |