很多本地代理都为Socks5或者HTTP代理,本篇将从理论与实践角度,解释二者原理。

本篇是代理技术鉴赏的一篇分支,更加细致的介绍了Socks5和HTTP代理。

Socks5代理于RFC 1928文档中定义,其是Socks4的升级版,在其基础上添加了认证机制、UDP代理和IPv6支持,Socks4已被Socks5完全替代。Socks5代理TCP时,分为认证请求通信3个阶段。

1、Socks5代理TCP

image.png

1.1 TCP认证

首先,客户端会与Socks5代理建立TCP三次握手,之后发送认证请求,格式如下:

VERNMETHODSMETHODS
111 to 255

VER:表示socks协议版本,值为0x05
NMETHODS:表示支持多少种验证方式,也就是后面METHODS字段的长度
METHODS:表示支持的验证方式,最多可提供255种,最少提供1种验证方式。

0x00 无须验证
0x01 GSSAPI
0x02 用户名/密码
0x03~0x7F IANA分配
0x80~0xFE 自定义验证方式
0xFF 没有可验证的方式(这种情况下socks服务器必须关闭连接)

流量示例:
image.png

socks5服务端收到消息后,选择一种认证方式并发送给客户端,格式如下:

VERMETHOD
11

流量示例:
image.png

然后进入选定的认证方法认证阶段,这里以用户名/密码认证方式为例,给出流量示例:
image.png
这里面用户名为bigbyto,密码为123456,然后服务端回复。
image.png

1.2 TCP请求

客户端认证后,就可以开始发送连接请求了,格式如下:

VERCMDRSVATYPDST.ADDRDST.PORT
110x001Variable2

VER:表示socks协议版本,值为0x05
CMD:请求命令类型,表示客户端希望代理执行的操作

0x01 CONNECT(TCP连接请求)
0x02 BIND(绑定端口,用于服务器反向连接)
0x03 UDP ASSOCIATE(UDP中继,用于UDP转发)

RSV:保留字段,必须填0x00。 ATYP:目标地址类型

0x01 IPv4地址(4字节)
0x03 域名(第一个字节为域名长度)
0x04 IPv6地址(16字节)

DST.ADDR:目标主机地址,格式取决于ATYP
DST.PORT:目标主机端口

大多数情况下,ATYP为域名,即客户端将域名直接传输给Socks5服务端,由服务端做DNS解析,由于Socks5服务端通常也在本地,故由后续的代理软件决定,如全局模式,就是在远端节点做DNS解析。这种情况下,客户端并不知道域名具体的IP,只知道已经通过代理转发给目的地址。

流量示例:
image.png
客户端请求访问a.baidu.com的80端口。

socks5服务端收到访问请求后,回复客户端,格式如下:

VERREPRSVATYPBND.ADDRBND.PORT
110x001Variable2

VER:协议版本,固定值为0x05。
REP:回复字段,表示服务器执行请求的结果:

0x00 成功
0x01 通用SOCKS服务器故障
0x02 连接不被规则集允许
0x03 网络不可达
0x04 主机不可达
0x05 连接被拒绝
0x06 TTL过期
0x07 不支持的命令
0x08 不支持的地址类型
0x09~0xFF 未分配

RSV:保留字段,固定为0x00。
ATYP:后续地址的类型:

0x01 IPv4地址
0x03 域名
0x04 IPv6地址

BND.ADDR:服务器绑定的地址。
BND.PORT:服务器绑定的端口号。

在最常见的CONNECT情况下,BND.ADDR和BND.PORT通常为0.0.0.0:0,只表示“连接成功”,具体绑定信息无意义。而BIND和UDP ASSOCIATE情况下,表示实际地址和端口,用于后续数据通道建立。

流量示例:
image.png

1.3 TCP通信

连接建立后,客户端就可以和正常访问目标服务一样通信了,此时socks5代理仅会改变传输层以下的数据,而应用层的数据将原封不动的转发给目标服务器。也就是说,现在就可以把socks5代理服务器,当作目标服务器通信了。

流量示例:
image.png
image.png

2、Socks5代理UDP

2.1 UDP认证

Socks5代理UDP时,认证阶段与代理TCP时一样,且认证过程用的TCP连接。

2.2 UDP请求

认证通过后,客户端发送UDP代理请求,格式如下:

VERCMDRSVATYPDST.ADDRDST.PORT
110x001Variable2

这个请求格式与Socks5代理TCP时相同,不过这里的CMD值是0x03,也就是UDP类型,说明本次请求是UDP请求,且目标地址和端口可以全0表示“尚不确定”。

Socks5代理收到客户端发来的请求后,创建一个UDP监听端口,并将这个监听信息发回客户端,格式如下:

VERREPRSVATYPBND.ADDRBND.PORT
110x001Variable2

这个回复格式依旧与Socks5代理TCP时相同,其中,BND.ADDR/BND.PORT的值为创建的UDP连接关联的地址和端口,客户端会直接将UDP数据发送到这个UDP连接中,所以上一个步骤接收的DST.ADDR/DST.PORT并没有太大意义。且在UDP通信阶段,请求阶段的TCP连接不能断开,否则UDP代理将结束。

2.3 UDP通信

客户端收来Socks5代理服务器发来的UDP端口后,就可以将本地的UDP数据发送到指定端口,格式如下:

RSVFRAGATYPDST.ADDRDST.PORTDATA
211Variable2Variable

RSV:保留值,始终为 0x0000
FRAG:分包序号,可能有以下值:
​ 0x00 这是一个不需要分包的 UDP 报文

0x01~0x7F 分包序号
0x80~0xFF 最高位是1,表示这个是最后一个分包

ATYP:地址类型,可能有以下值:
​ 0x01 IPV4 地址(占 4 字节)

0x03 域名(第一字节为域名长度,后面为域名字符)
0x04 IPV6 地址(占 16 字节)

DST.ADDR:目标地址
DST.PORT:目标端口
DATA:UDP数据

相较于TCP代理,UDP代理在本地新开了一个UDP端口,但仍然与Socks5的TCP端口保持连接。但是,实际上很多Socks5代理工具并没有实现UDP代理功能[1]。目前代理UDP的方法还是启用TUN模式。

3、HTTP代理

HTTP代理可以代理HTTP、HTTPS以及任何基于TCP的流量。HTTP分为正向代理和反向代理。正向代理为客户端服务,而反向代理是针对服务端来说的,如nginx的反向代理。

HTTP 1.1中,新增了CONNECT方法,使得HTTP能够代理任何基于TCP的流量,如可利用HTTP代理SSH流量,而HTTP反向代理中,增加了WebSocket机制,使得其也能够代理任何基于TCP的流量,科学上网工具常用WS协议。

HTTP代理在代理HTTP流量时,代理理解并转发HTTP请求内容,用GET/POST等普通方法。流量示例如下:

image.png

HTTP在代理HTTPS、SSH等TCP流量时,会调用CONNECT方法,为客户端打开到目标主机的原始TCP连接并建立隧道。

HTTP代理SSH流量示例如下:

image.png

一些杂谈

由于Socks5和HTTP的服务端都没有带加密功能,在互联网上明文传输数据,HTTP中的认证也仅是做了Base64编码,所以极其不安全,如今已经将二者的应用场景从远端移到了本地。

浏览器能创建的UDP连接只有QUIC(HTTP 3.0)和WebRTC,其中WebRTC是正统的UDP。不过这两者都不会走浏览器或系统代理,只有在开启了TUN模式时,才可能会走,具体还要看代理节点对UDP的支持程度。

WebRTC使用独立的网络栈,直接创建系统级UDP socket,不经过浏览器的代理模块,所以不会走浏览器或ZeroOmega设置的Socks5代理。WebRTC Control等防止WebRTC泄露IP的扩展工具,都是通过禁用STUN协议来的。

DNS不算浏览器产生的,它是由浏览器调用系统API产生的。如果浏览器安装了代理插件,则会直接忽视系统代理,例如代理插件设置了直连,系统设置了代理,那么浏览器还是会走直连。

References

[1] https://www.txthinking.com/talks/articles/socks5-and-http-proxy.article

标签: Proxy, HTTP, Socks5

添加新评论