首先说一点,
shadowsocks
使用的就是
socks5
协议
RFC文档
Username/Password Authentication for SOCKS V5
介绍
socks5
is designed to provide a framework for client-server applications in both the TCP and UDP domains to conveniently and securely use the services of a network firewall
socks5
作为应用层和传输层的中间层,不提供传输层以下的服务,比如网络层的ICMP
报文是无法通过Socks5
协议来进行转发的
当防火墙后的客户端要访问外部的服务器时,就跟socks代理服务器连接。该协议设计之初是为了让有权限的用户可以穿过过防火墙的限制,使得高权限用户可以访问外部资源
Socks5
协议通信过程
When a TCP-based client wishes to establish a connection to an object that is reachable only via a firewall (such determination is left up to the implementation), it must open a TCP connection to the appropriate SOCKS port on the SOCKS server system.
现在我们的socks5
服务位于TCP
的1080
端口,Client
成功与Server
建立了TCP
连接,这时Client
便可以与Server
协商认证方法,协商完成之后进行身份认证并发送转接请求,此时只有两种结果:认证成功、拒绝请求
Client
首先给Server
发送的信息格式如下
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+
1 to 255 表示该字段长度的范围为1~255字节
VER
:长度为1byte
的版本号
NMETHODS
:表示Client
提供的认证方法的数量
METHODS
:METHODS
代号: X'hh'
,16
进制表示
- X’00’ NO AUTHENTICATION REQUIRED
- X’01’ GSSAPI
-
**X'02' USERNAME/PASSWORD**
-
**X'03' to X'7F' IANA ASSIGNED**
-
**X'80' to X'FE' RESERVED FOR PRIVATE METHODS**
-
**X'FF' NO ACCEPTABLE METHODS**
Server
接收到Client
的信息后,返回如下格式的响应消息:
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |
+----+--------+
METHOD
字段表示Server
所选定的认证方法,若其值为X'FF'
,则表示Server
什么认证方法都没有指定,此时Client
与Server
之间的连接会关闭
Socks5
身份认证
The client and server then enter a method-specific sub-negotiation
现在我们来查阅Username/Password Authentication for SOCKS V5 RFC 1929
The protocol specification for SOCKS Version 5 specifies a generalized framework for the use of arbitrary authentication
protocols in the initial socks connection setup. This document
describes one of those protocols, as it fits into the SOCKS Version 5
authentication “subnegotiation”.
Once the SOCKS V5 server has started, and the client has selected the
Username/Password Authentication protocol, the Username/Password
subnegotiation begins
This begins with the client producing a
Username/Password request,请求报文格式如下:
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
1 to 255 表示该字段长度的范围为1~255字节
VER
:版本号ULEN
:用于表示UNAME
字段的长度UNAME
:username
PLEN
:用于表示PASSWD
字段的长度PASSWD
:username
对应的password
The server verifies the supplied UNAME and PASSWD, and sends the
following response:
+----+--------+
|VER | STATUS |
+----+--------+
| 1 | 1 |
+----+--------+
若STATUS
字段值为X'00'
,则认证成功,除此之位的任何值均表示failure
,此时Client
和Server
之间的连接将会关闭
这种认证方式是有安全隐患的,用户名和密码都是明文传输的,如果攻击者渗透到了内网,则很容易嗅探到用户名和密码
认证完成之后,Client
向Server
发送请求包,格式如下:
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
- VER
-
protocol version: X'05'
-
**CMD**
- CONNECT X’01’
-
**BIND X'02'**
-
**UDP ASSOCIATE X'03'**
-
**RSV**
-
RESERVED,置零
-
-
**ATYP** (address type of following address)有以下三个值可以选择
-
**IP V4 address: X'01'**
-
**DOMAINNAME: X'03'**
-
**IP V6 address: X'04'**
-
-
**DST.ADDR**
-
desired destination address
-
-
**DST.PORT**
-
desired destination port in network octet order
-
稍微提一下上面ATYP
的DOMAINNAME
,如果指定了该选项,则后面的DST.ADDR
字段中存放的是FQDN
,它的第一个字节表示后面的FQDN
占用的字节数,there is no terminating NUL octet*(octet
表示8
位一组)*
Server
对请求进行基于源和目的地址的审核之后会向Client
发送一个或者多个响应报文,报文格式如下:
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
- VER
- protocol version: X’05’
-
**REP(应答结果)**:
-
X'00' succeeded
-
X'01' general SOCKS server failure
-
X'02' connection not allowed by ruleset
-
X'03' Network unreachable
-
X'04' Host unreachable
-
X'05' Connection refused
-
X'06' TTL expired
-
X'07' Command not supported
-
X'08' Address type not supported
-
X'09' to X'FF' unassigned
-
-
-
**RSV** **(RESERVED)保留,置零**
- ATYP (address type of following address)
-
IP V4 address: X'01'
-
DOMAINNAME: X'03'
-
IP V6 address: X'04'
-
-
**BND.ADDR** **(server bound address)**
-
**BND.PORT** **(server bound port in network octet order)**
下面我们按照Client
请求中CMD
的三个值来对响应报文进行讲解:
CONNECT
BND.PORT
和BND.ADDR
的值与Client
发给Server
的报文中的DST.ADDR
和DST.PORT
字段的值是相等的
Client
的源地址和目的地址用来进行请求审核
BIND
The BIND request is used in protocols which require the client to
accept connections from the server. FTP is a well-known example,
which uses the primary client-to-server connection for commands and
status reports, but may use a server-to-client connection for
transferring data on demand (e.g. LS, GET, PUT)
It is expected that the client side of an application protocol will
use the BIND request only to establish secondary connections after a
primary connection is established using CONNECT
意思是,我们认为Client
使用BIND
命令的原因只有一个,那就是在使用CONNECT
命令建立了第一个连接之后,需要建立第二个连接,就像FTP
服务,第一个connection
用于命令交互,第二个connection
用于传输数据,这时SERVER
使用DST.ADDR
字段和DST.PORT
字段来进行请求的审核
socks
服务器作为一个中间人
一头连接Client
,这时Server
会创建和绑定一个新的socket
,并向Client
发送第一个响应
另一头连接Client
让它去连接的ADDR
和PORT
,当另一头的连接建立成功后,第二个响应会被发送给Client
UDP ASSOCIATE
UDP ASSOCIATE
命令通常是要求建立一个UDP
中继来处理到来的UDP
数据包,数据包中的DST.ADDR
和DST.PORT
字段包含了Client
希望用来发送UDP
报文的地址和端口号,这样一来,Server
就能通过ADDR
和PORT
来限制连接(相对于Server
的另一端,就是Client
委托Server
访问的那一端,不是来自指定地址和端口的报文将不被转发),如果主机没有指定这两个字段的值,将会被填充为0
当TCP
连接中断的时候,UDP association
也会中断,因为它本来就是建立在Client
和Server
的TCP
连接之上的
响应过程
除X'00'
之外的所有响应码都表明了请求失败,发送完响应报文之后Server
会中断连接,This must be no more than 10 seconds after detecting the
condition that caused a failure
如果响应报文的REP
字段为X'00'
,则开始转发报文
对UDP
服务的处理过程
意思就是Client
希望Server
能帮自己去和远程服务器进行UDP
连接
Each UDP datagram carries a UDP request
header with it**(首部格式)**:
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
- RSV
- Reserved X’0000’
-
**FRAG**
- X’00’表示没有其余分片,1-127表示它在所有分片中的编号
-
**ATYP** **(address type of following addresses)**
-
IP V4 address: X'01'
-
DOMAINNAME: X'03'
-
IP V6 address: X'04'
-
-
**DST.ADDR**
Client
委托Server
转发的报文的目的地址
-
**DST.PORT**
Client
委托Server
转发的报文的目的端口
-
**DATA**
-
user data
-
远程UDP
服务器需要从SOCKS
服务器获得Client
的IP
,来自其他IP
的报文将会被丢弃
每个Client
都有一个组装队列,用于组装被分片的UDP
报文,同时拥有一个超时定时器
,组装工作需要在此时间内完成,否则重装队列会被初始化,分片将会被丢弃,or when a new datagram arrives carrying a FRAG field whose value is less
than the highest FRAG value processed for this fragment sequence.
The reassembly timer MUST be no less than 5 seconds. It is
recommended that fragmentation be avoided by applications wherever
possible.