Socks5代理

xiaoxiao2021-02-28  198

jsocks的Java版本实现

代理就是中间人,一人分饰两角:客户端眼中的目标服务器,目标服务器眼中的客户端——这意味着他必须同时满足C/S 双方的规范。再细分,如果只是简单的 pipe C/S 两端数据,那他就是个“透明代理”;一旦他对请求或响应进行了修改,那就是“非透明代理”。

SOCKS5 是常用的代理协议的一种。它是Socks协议的第五版,相对于第四版增加了身份验证,UDP,IPV6的支持。

SOCKS5 旨在提供一种通用的代理服务,工作在应用层和传输层之间,只是传递传输层网络数据包(TCP/UDP),对于应用层的协议并不关心。交互大概分为这么几步:

1. 客户端发送认证协商

2. 代理服务器就认证协商进行回复(如拒绝则本次会话结束)

1. 如需GSSAPI或用户名/密码认证,客户端发送认证信息

2. 代理服务器就对应项进行鉴权,并进行回复或拒绝

3. 客户端发送希望连接的目标信息

4. 代理服务器就连接信息进行确认或拒绝

5. 【非协议内容】:代理服务器连接目标并 pipe 到客户端、

SOCKS5在使用时是典型的CS模式的。SOCKS5服务可以分成两大功能,身份认证和代理服务。每个功能又支持不定的多种方法(Method)。

身份认证常用的方法是不需认证(No Authentication Required)和用户名/密码认证(Username/Password),多数应用软件包括我们监控CU都只支持这两种方法。

代理服务的模式有连接(Connect),绑定(Bind)和UDP穿透(UDP Associate)。

1. 认证

认证格式为 :

VERNMETHODSMETHODS111-255

认证方法:

0x00: NO AUTHENTICATION REQUIRED0x01: GSSAPI0x02: USERNAME/PASSWORD0x03: to X’7F’ IANA ASSIGNED0x80: to X’FE’ RESERVED FOR PRIVATE METHODS0xFF: NO ACCEPTABLE METHODS

1.1 客户端 -> 代理服务器,请求认证:

版本号(1字节)可供选认证方法(1字节)选择的方法(1~255字节) 固定为5选了多少种

都有上表中哪些方法

例如:客户端发给服务端:0x5 0x01 0x00 不认证 ,或者 0x05 0x02 0x00  0x02支持用户名密码认证或者不认证共两种方式。

1.2 代理服务器  -> 客户端,响应认证:

服务器从客户端提供的方法中选择一个并通过以下消息通知客户端(以字节为单位

版本号(1字节)

确认认证的方法

 固定为5

认证方法列表的某项: 0x00,则无需客户端发送进一步认证的信息 0x01,则需要客户端进行进一步认证,细节见 RFC1929 0x02,需要用户名密码认证,细节见RFC2743

0xFF,则相当于拒绝请求,客户端只能关闭连接

例如:服务端发给客户端:0x5  0x00 不认证 ,或者 0x05 0x02 用户名密码认证

如果采用用户名密码认证,需要客户端发送用户名和密码;

1.3 SOCKS5 用户名密码认证方式

在客户端、服务端协商使用用户名密码认证后,客户端发出用户名密码,格式为(以字节为单位):

鉴定协议版本用户名长度用户名密码长度密码11动态1动态

鉴定协议版本目前为 0x01。 比如客户端发给服务器:0x01,用户名长度占一位 ,用户 密码长度占一位,密码。

服务器鉴定后发出如下回应:

鉴定协议版本鉴定状态11

其中鉴定状态 0x00 表示成功,0x01 表示失败。

2. 请求信息

2.1 客户端 -> 代理服务器,发送目标信息:

VERCMDRSVATYPDST.ADDRDST.PORT110x001动态2

命令字段说明:

版本号(1字节)命令(1字节)保留(1字节)求类型(1字节)地址(不定长)端口(2字节) 固定为50x01: CONNECT 0x02: BIND 0x03:UDP ASSOCIATE固定为 0x000x01: IP V4 地址 0x03: 域名 0x04: IP V6 地址 如果请求 类型是域名, 第个1字节为 域名的长度  CONNECT:  用于客户端请求服务器进行代理BIND:  用于客户端向服务器上报自己的反向连接监听地址(应用场景如 FTP 下载,客户端需要接受来自服务器的连接UDP ASSOCIATE:用于请求建立到 UDP 数据报中继的连接

2.2 代理服务器 -> 客户端,确认连接:

版本号(1字节)确认回应(1字节)保留(1字节)响应类型(1字节)地址(不定长)端口(2字节) 固定为50x00: succeeded 0x01: general SOCKS server failure 0x02: connection not allowed by ruleset 0x03: Network unreachable 0x04: Host unreachable 0x05: Connection refused 0x06: TTL expired 0x07: Command not supported 0x08: Address type not supported 0x09: to X’FF’ unassigned固定为 0x00仅用于响应客 户端BIND命令: 0x01: IP V4 地址 0x03: 域名 0x04: IP V6 地址 仅用于响应客 户端BIND命令: 如果请求 类型是域名, 第个1字节为 域名的长度仅用于响应客 户端BIND命令

可以看出,在代理服务器确认回应为 0x00 时,此次 SOCKS5 协议协商部分顺利完成,宣告进入到数据传输阶段(也可以说,这之后发生的事已经与SOCKS5协议无关)。

 

3.UDP穿透

UDP穿透(UDP Associate)是SOCKS5新加入的功能。客户端首先TCP连接SOCKS5代理服务器,并完成认证过程。

3.1UDP穿透请求

客户端会用通过认证的这个TCP连接发送UDP穿透请求,信令格式如下:

    +----+-----+-------+------+----------+----------+

    |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |

    +----+-----+-------+------+----------+----------+

    | 1  |  1  | X'00' |  1   | Variable |    2     |

    +----+-----+-------+------+----------+----------+

其中各项:

o  VER    协议版本,对于SOCKS5都是 5。

o  CMD      要请求的命令,UDP穿透填3。 其它的CONNECT是1,BIND是2。

o  RSV    保留字段,填0。

o  ATYP   地址类型,我们用IPV4,填1。域名的话填3,IPV6的话填4。

o  DST.ADDR   IP地址。对于UDP穿透来说,好像没有什么意义,填0(也就是127.0.0.1)。

o  DST.PORT  这个很重要,要填客户端想发送/接收UDP包的本地端口。后面在发送UDP包时代理服务器会检测收到的UDP包的源端口,只有和这里填入的端口号符合的包才会被处理。

 

3.2 UDP穿透应答

代理服务器会回应客户端的请求,消息格式如下:

+-----+------+-------+-------+------------+-------+

|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |

+-----+------+-------+-------+------------+-------+

 |  1   |   1   |  X'00' |   1    | Variable |    2   |

其中:

o  VER    协议版本,对于SOCKS5都是 5。

o  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

      o  RSV    保留字段。

      o  ATYP   后面IP地址的格式,含义如下:

      IP V4 address: X'01'

DOMAINNAME: X'03'

      IP V6 address: X'04'

      o  BND.ADDR   此UDP穿透通道对应的代理服务器地址。

      o  BND.PORT    此UDP穿透通道对应的代理服务器端口。

至此,UDP穿透通道已经被建起来了,客户端只要按标准格式将UDP包发往上述地址端口,UDP包就会被代理服务器转发出去。

 

3.3UDP包发出

上面交互信令中都没有提到客户端想通过代理访问的远端服务器地址。UDP包的最终目的地是通过在原始UDP包数据前加一个包头来实现的。包头的格式如下:

    +-----+------+------+----------+----------+----------+

    |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |

    +-----+------+------+----------+----------+----------+

    |  2  |  1   |  1   | Variable |    2     | Variable |

其中:

o  RSV  保留字段,填0。

o  FRAG    当前分片序号,我们没有分片,填0。

o  ATYP    地址类型,和前面的几个一样。IPV4填 1 。

o  DST.ADDR  UDP包最终的目的地址。

o  DST.PORT   UDP包最终的目的端口。

o  DATA     原始的UDP包的数据。

发出的UDP包中的DATA部分会被代理服务器转发到包头中填入的最终目的地址。也就是说,我们用一路UDP穿透通道可以向不同的服务器发送数据。因为包头会被代理服务器去掉,所以远端服务器是不用知道客户端是否使用了代理。注意,一个TCP连接只能处理一路udp转发请求。

通过上面分析我们可以大体上总结到透过Socks5进行UDP编程需要注意的几点:   1、 Socks5编程的身份验证   由于防火墙作用几乎是隔绝内外的非正常连接,而Socket可以通过任何端口连接到外部,所以作为对Socket4的改进,Socket5增加了对 socket协议访问的验证功能。这些验证功能没有规定一定采用什么方法,一般看防火墙自身支持以及客户端能够支持什么方法,这意味着作为客户端必须将自 己支持的方法在协商阶段之初就告诉代理服务器,而代理服务器自己根据已经实现支持哪种验证方法而选择特定的方法回复客户端。意味着针对不同的代理服务器以 及不同的客户端,很可能对于验证方法支持上有区别,需要视具体的应用环境而定。这些增加了Socket5客户端以及Proxy server软件的编写难度,但是增强了安全性。   1、 TCP保持重要性   要发送穿透代理服务器的UDP数据报,其实首先需要建立客户端到代理服务器的TCP连接,通过一系列的交互,获得代理服务器的许可才能够发送出去(同 时代理服务器业记录下连接的在Socks5服务的客户IP和端口),也确保从远端发回的数据能够通过代理服务启发回给某个UDP客户端(因为它登记了一个 关于Socket UDP的通路映射)。所以为了发送UDP数据,必须建立和保持这个TCP数据。RFC1928也提到,不能取得代理服务器的通道后就关闭TCP连接,否则 代理服务器以为UDP Socket通过代理的请求已经结束,不需要继续保留UDP的对外Socket映射记录,从而导致每发送一次UDP就要重新建立TCP连接协商UDP映 射,增加不必要的麻烦。所以,我们需要保持UDP客户端到到代理服务器的TCP连接持久,不必显式关闭它。   2、 UDP本地端口选定   UDP大多数是同具体端口相关的,所以一定要在同代理服务器协商UDP映射时告知客户端UDP的端口。一来将UDP同某个端口绑定,使得代理服务器接 收UDP数据并转发,二来也告诉了代理服务器将来在某个端口发出去后得到的反馈数据也按照线路返回给客户的此端口。这一点很重要.   3、 TCP/UDP连接二重性   可以看到Socks5 的使用会占用至少一个TCP连接,这样导致代理服务器的负担很重。所以在具体的应用时,需要考虑关于代理服务器的存在的负载问题。   以上即关于UDP穿透Socks5代理的一点心得,希望能够得到大家的指正。

 

转载请注明原文地址: https://www.6miu.com/read-2960642.html

最新回复(0)