写点什么

网络协议之: 一定要大写的 SOCKS

作者:程序那些事
  • 2021 年 11 月 27 日
  • 本文字数:2937 字

    阅读完需:约 10 分钟

网络协议之:一定要大写的SOCKS

简介很久很久以前,人们还穿的是草鞋,草鞋虽然穿着舒服,但是不够美观。然后人们就发现,用动物的皮也可以做成鞋,于是出现了皮鞋。但是皮鞋穿着磨脚,于是人们又发明了 socks,套在脚上,代替脚跟鞋子接触,既提高了舒适感,也减少了磨损,简直是一举两得的事情,非常完美。


在网络世界,也存在这样的 socks,为了和真实世界的 socks 进行区分,这里我们使用大写的 SOCKS。


SOCKS 就是我们今天要讲解的网络代理协议。


SOCKS 的故事在讲解 SOCKS 之前,我们回顾一下 OSI 网络七层协议。


OSI 是 Open System Interconnect 的缩写,意为开放式系统互联。


而 SOCKS 也是一种网络协议,它的作用和 socks 一样,用来代替客户端和服务器端进行连接,也就是代理协议。


SOCKS 在 OSI 七层协议的第五层,也就是会话层中,它处于表现层和传输层的中间。从上图可以看到 SOCKS 的底层就是 TCP 和 UDP 协议。


作为一个代理协议,SOCKS 可以提供基于 TCP 和 UDP 的代理,相较于 HTTP 的代理而言,SOCKS 的代理更加底层,所以应用场景也会更多。


通常来说,SOCKS 的标准端口是 1080。


SOCKS 的历史每个协议都有自己的发展史,SOCKS 也不例外,如果要把所有协议的发展史以故事的形式讲述起来一定会很有意思,大家可以期待一下,说不定某天这样的文章就出现了。


代理是网络中的一项基本功能,SOCKS 代理最先是由美国 MIPS 科技公司的 David Koblas 设计的。MIPS 公司以开发 MIPS 架构和基于该架构的一系列 RISC CPU 芯片而闻名。不过后面被一系列的收购,最终 MIPS 架构被放弃了,转而支持 RISC-V 架构。


MIPS 在 1992 年被 Silicon Graphics 收购了,在那一年 Koblas 发表了关于 SOCKS 的论文,SOCKS 一举成名。


SOCKS 最广泛使用的协议版本是 4 和 5。SOCKS4 是 NEC 的 Ying-Da Lee 发明的。因为 SOCKS 4 中并没有关于安全方面的约定,但是对于现在的网络来说,安全越来越重要,所以出现了 SOCKS5,SOCKS5 协议最初是一种使防火墙和其他安全产品更易于管理的安全协议。


SOCKS 协议的具体内容现在常用的 SOCKS 协议主要有 SOCKS4、SOCKS4a 和 SOCKS5。本节将会详细讲诉他们的协议构成。


SOCKS4 先看一下 SOCKS4 的请求数据 package 长得什么样子的:


含义 VER CMD DSTPORT DSTIP ID 字节个数 1 1 2 4 可变 VER 占用 1 个字节,表示的是 SOCKS 协议的版本号,对于 SOCKS4 来说,这个值是 0x04。


CMD 占用 1 个字节,表示的是要执行命令的代码,有两个选择,其中 0x01 表示建立一个 TCP/IP 流连接,0x02 表示建立一个 TCP/IP 端口绑定。


DSTPORT 占用 2 个字节,表示目标端口号。


DESTIP 占用 4 个字节,表示的是 IPv4 地址。


ID 占用字节不定,表示的是用户 ID。


对于请求数据,相应的返回数据如下:


含义 VN REP DSTPORT DSTIP 字节个数 1 1 2 4VN 占用 1 个字节,表示是返回的消息的版本。


REP 占用 1 个字节,表示返回的 code:


字节 含义 0x5A 请求授权 0x5B 请求拒绝或者请求失败 0x5C 因为请求不包含客户端 ID 或者服务器端无法连接客户端而失败 0x5D 因为客户端 ID 不匹配而失败 DSTPORT 占用两个字节,表示目的地的端口,如果没有绑定的话,则为空。


DSTIP 占用 4 个字节,表示客户端绑定的目的地的 IP 地址。


举个例子,如果客户端想使用 SOCKS4 从 Fred 连接到 66.102.7.99:80,请求如下:


0x04 | 0x01 | 0x00 0x50 | 0x42 0x66 0x07 0x63 | 0x46 0x72 0x65 0x64 0x00 其中最后一个字段是 Fred 的 ASCII 编码。


如果服务器端返回 OK,则对应的响应如下:


0x00 | 0x5A | 0xXX 0xXX | 0xXX 0xXX 0xXX 0xXX 其中 0xXX 可以是任意值。


当连接建立完毕之后,所有的 SOCKS 客户端到 SOCKS 服务器端的请求都会转发到 66.102.7.99。


SOCKS4a 因为 SOCKS4 只能指定目的服务器的 IP 地址,这对应服务器有多个 IP 的情况下会有很严重的限制。所以 SOCK4a 对 SOCK4 进行了扩展,可以支持目标服务器的域名。


SOCKS4a 也是由 SOCKS4 的作者 Ying-Da Lee,提出来的。我们看下 SOCKS4a 的请求格式:


含义 VER CMD DSTPORT DSTIP ID DOMAIN 字节个数 1 1 2 4 可变 variableSOCKS4a 是在 SOCKS4 的最后加入了 domain。


DOMAIN 表示的是要连接到的目标服务器的域名。使用 null (0x00)来结尾。对应的 DSTIP 的前三个字节设置为 NULL,最后一个字节设置成一个非 0 的值。


服务端的响应和 SOCKS4 是一样的。


SOCKS5 虽然 SOCKS5 是 SOCKS 的最新版本,但是 SOCKS5 和 SOCKS4 是不兼容的。SOCKS5 支持认证,并且提供了对 IPv6 和 UDP 的支持。其中 UDP 可以用来进行 DNS lookups。它的交互流程如下所示:


客户端和服务器端进行连接,并发送一个 greeting 消息,同时包含了支持的认证方法列表。服务器端选择一个支持的认证方法,如果都不支持,则发送失败响应。


根据选中的认证方法,客户端和服务器进行后续的认证交互,交互流程跟选中的认证方法相关。


客户端以 SOCKS4 相似的方式发送连接请求。


服务器端发送和 SOCKS4 相似的响应。


我们看下 greeting 消息的格式:


含义 VER NAUTH AUTH 字节个数 1 1 可变字节 VER 占用 1 个字节表示 SOCKS 的版本号,这里是 0x05。


NAUTH 占用 1 个字节,表示支持的认证方法的个数。


AUTH 是可变字节,表示的是支持的认证方法。一个字节表示一个方法,支持的方法如下:


0x00: 没有认证0x01: GSSAPI 0x02: 用户名/密码 (RFC 1929)0x03–0x7F: methods assigned by IANA    0x03: Challenge-Handshake Authentication Protocol    0x04: 未分配    0x05: Challenge-Response Authentication Method    0x06: Secure Sockets Layer    0x07: NDS Authentication    0x08: Multi-Authentication Framework    0x09: JSON Parameter Block    0x0A–0x7F: 未分配0x80–0xFE: 内部使用的保留方法
复制代码


对应的服务器端的响应如下:


含义 VER CAUTH 字节个数 1 1VER 占用 1 个字节,表示的是版本号。对于 SOCKS5 来说,它的值是 0x05。


CAUTH 占用 1 个字节,表示选中的认证方法。如果没有被选中,则设置为 0xFF。


选好认证方法之后,接下来就是客户端和服务器端的认证交互了,这里我们选择最基本的用户名和密码 0x02 认证为例。


客户端发送认证请求:


含义 VER IDLEN ID PWLEN PW 字节个数 1 1 (1-255) 1 (1-255)VER 占用 1 个字节表示当前用户名和密码认证的版本。


IDLEN 占用 1 个字节,表示用户名的长度。


ID 占用 1 到 255 个字节,表示用户名。


PWLEN 占用 1 个字节,表示密码的长度。


PW 就是密码。


对应的服务器端的响应如下:


含义 VER STATUS 字节个数 1 1VER 占用 1 个字节,表示版本号。


STATUS 占用 1 个字节,表示服务器的响应状态。


接下来,客户端就可以和服务器端发送建立连接消息了:


含义 VER CMD RSV DSTADDR DSTPORT 字节个数 1 1 1 可变字节 2CMD 是连接可选的命令,0x01 表示建立 TCP/IP 流连接,表示建立 TCP/IP 端口绑定,0x03 表示连接一个 UDP 端口。


RSV 是保留字节,必须是 0x00。


DSTADDR 是 SOCKS5 的地址。地址的定义是这样的:


含义 TYPE ADDR 字节个数 1 可变字节 TYPE 表示地址的类型,0x01 是 IPv4 地址,0x03 是域名,0x04 是 IPv6 地址。


ADDR 表示的是地址,如果是 IPv4,则使用 4 个字节,如果是域名,则第一个字节表示长度,后面字节表示域名。如果是 IPv6 地址,则使用 16 个字节。


对应的服务器端的响应如下:


含义 VER STATUS RSV BNDADDR BNDPORT 字节个数 1 1 1 可变字节 2 总结以上就是 SOCKS4 和 SOCKS5 的详细协议内容。注意,SOCKS 一定要大写!


本文已收录于 http://www.flydean.com/09-socks/


最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!


欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2 小时前阅读数: 5
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
网络协议之:一定要大写的SOCKS