Fork me on GitHub

谈谈ss和socks5协议

ss和socks5协议

本文首发于个人博客:www.thorns.cn

前言:由于最近公司需要一个自己的代理服务,所以花了一周的时间去研究了下shadowsocks实现的原理,以及socks5协议。

认识Shadowsocks

Shadowsocks是一个能骗过GFW的网络代理工具,它把我们要访问的数据请求,比如google,youtube,facebook…进行加密后传输到GFW外的服务端,由服务端去访问目标站点再加密返回给我们,网络中的GFW由于不知道传输的原内容是什么只好放行,于是就完成了我们所谓的”翻墙”。

Shadowsocks原理

SS(Shadowsocks)由两部分组成,运行在本地的ss-local和防火墙之外服务器上的ss-server。ss-local的职责是在本机启动和监听一个服务,本地软件的网络请求都会先发送到ss-local,ss-local收到来自本地软件的网络请求后,把要传输的原数据根据用户配置的加密方法和密码进行加密,再转发到服务端。ss-server的职责是在墙外服务器启动和监听一个服务,当服务端收到ss-local转发过来的数据时,会根据用户配置的加密方法和密码对数据进行解密,同时还会解socks5协议,然后会把解密后的数据转发到真正的请求目标服务地址(例如Google),以下是整个流程图.
avatar

Socks5协议介绍

SS的数据传输是建立在socks5协议之上的,Socks5是TCP/IP的网络代理协议,socks5有协商认证请求部分,个人更喜欢把他叫做Protocol Handshake。

协商版本和验证方法

当我们的客户端向服务端建立连接之后,客户端就会向服务端进行协商,发送的数据包如下:
avatar

其中各字段的含义如下:
VER:代表SOCKS的版本,SOCKS5 默认为0x05,固定长度一个字节。
NMETHODS:表示第三个字段的长度(也就是有几种认证方法),长度也是一个字节
METHODS:表示客户端支持的验证方式,可以有多种,长度1-255字节。
支持的验证方式有:

  • 0x00:NO AUTHENTICATION REQUIRED(不需要验证)
  • 0x01:GSSAPI (通用安全服务应用程序接口)
  • 0x02:USERNAME/PASSWD(用户名密码)
  • 0x03:IANA ASSIGNED(至 0x’7F’ IANA 分配)
  • 0x80:RESERVED FOR PRIVATE METHODS(至 0x’FE’ 私人方法保留)
  • 0xff:NO ACCEPTABLE METHODS(没有可接受的方法)
    当服务端收到客户端的验证机信息之后,就要回应客户端提供哪种验证方式的信息。服务端回应的包格式如下:
    avatar
  • VER:代表SOCKS的版本,SOCKS5默认为0x05,长度一个字节。
  • METHOD:代表服务端回应客户端需要哪种验证方式,可以为上面六种验证方式之一

举个例子,比如客户端发送的包是 0x05 0x01 0x02,如果服务端不需要验证就会返回0X05 0X00,需要验证就会返回0x05 0x02,接下来客户端就需要进行认证这一步,也就是把用户名和密码发送给服务端进行认证,在这里我就不介绍认证这一步了,直接说请求这一步。

请求

客户端发起的连接由服务端验证通过后,客户端下一步就应该把要访问的目的网站地址给服务端,服务端得到地址后再去请求真正的目标服务。这一步客户端需要发送的包格式如下:
avatar

各个字段含义如下:

  • VER:socks的版本
  • CMD:代表客户端请求的类型,值长度1个字节,有三种类型:
    1. Connect: 0x01
    2. BIND: 0x02
    3. UDP: 0x03
  • RSV:保留字段,默认0x00,长度1个字节
  • ATYP:代表请求的远程服务器地址类型,长度1个字节,三种类型:
    1. IPV4: 0x01
    2. IPV6: 0x04
    3. DOMAINNAME: 0x03
  • DST.ADDR:代表远程服务器的地址,根据ATYP进行解析,值长度不定
  • DST.PORT:代表远程服务器的端口,值长度2个字节

服务端再收到客户端告诉的目标服务地址后,便和目标进行连接,不管成功与否,服务器都应该把连接的结果告诉客户端.如果连接成功的情况下,服务端返回的包格式如下:
avatar

各个字段含义如下:

  • REP:代表响应码,值长度1个字节,有如下类型
    1. 0x00:succeeded(成功)
    2. 0x01:general SOCKS server failure(socks5服务器失败)
    3. 0x02:connection not allowed by ruleset
    4. 0x03:Network unreachable(网络无法访问)
    5. 0x04:Host unreachable(主机无法访问)
    6. 0x05:Connection refused(拒绝连接)
    7. 0x06:TTL expired(TTL 超时)
    8. 0x07:Command not supported(命令不支持)
    9. 0x08:Address type not supported(地址类型不受支持)
    10. 0x09:to 0xFF unassigned
  • RSV:保留字,值长度一字节
  • BND.ADDR:表示绑定地址,值长度不定
  • BND.PORT:表示绑定端口,值长度2字节

数据转发

客户端在收到来自服务器成功的响应后,就会开始发送数据给本地代理,本地代理加密后进行转发给服务端,服务端解密之后访问最终目标服务。

总结

SOCKS5协议的目的就是为了把原本应该在本机直接请求目标服务的流程,放到了服务端去代理 客户端访问.运行流程如下:

本地代理和服务端协商认证请求
本地代理告诉服务端目标服务的地址
服务端去访问目标服务,成功后告诉本地代理
本机开始发送原本应发送到目标服务的数据给服务端,由服务端完成数据转发

注:以上内容有很多部分都是参考RFC1928,和其他博主发表的博文,借鉴而来。如果感觉有什么地方不对或者不同见解的,都可以提出争议,以立即改正。

您的赞赏是对我最大的支持,谢谢!