Proxy
Proxy Server 代理服务器
Basic
- Define:代理服务器是位于客户端和目标服务器之间的中间服务器。
- Func:隐藏真实IP、加速访问、访问限制内容、过滤内容
Socket Secure 5
- Socks5 是一个万能的中间人代理协议,可以绕过防火墙、隐藏 IP、访问受限内容,并支持更广泛的网络应用
- 支持 TCP 和 UDP,比 HTTP 代理更强大
- TCP:传输控制协议(可靠但慢)三次握手协议 ACK数据确认 belike 打电话
- UDP:用户数据报协议(快但不可靠)不建立连接,直接“扔包” belike 发短信
- 本协议旨在为基于 TCP 和 UDP 的客户端-服务器应用程序提供一种方便且安全地使用防火墙服务的机制
- 介于应用层与传输层之间的“中间层”
代理客户端
在我们的简单代理服务器中, 用户请求的所有流量都会直接从服务器所在的机器发出:
1 |
|
你也可以让流量经过另一台 socks5 代理服务器:
1 |
|
为此, 你需要在 Proxy 1 上实现一个 socks5 代理客户端。这个客户端会将 socks5 请求重新包装成 socks5 请求并发送给 Proxy 2。
Procedure for TCP-based Clients
当一个基于 TCP 的客户端希望建立连接,而目标对象只能通过防火墙访问(具体如何判断由实现决定),它必须向 SOCKS 服务器的指定端口(默认是 TCP 端口 1080)建立一个 TCP 连接。
如果连接成功,客户端接下来将发起 认证方法协商,完成认证过程后发送中继请求。SOCKS 服务器评估请求,然后决定是否建立连接或拒绝请求。
客户端首先向服务器发送一个“版本标识/方法选择”报文:
1 |
|
rmk:这是字节数
- VER:设置为 X’05’,表示协议版本 5;
- NMETHODS:表示 METHODS 字段中包含的认证方法数量;
- METHODS:列出客户端支持的认证方法。
服务器收到后,从 METHODS 中选择一种方法,并返回如下回应:
1 |
|
请求格式
一旦方法协商完成,客户端发送具体请求。若认证方法提供完整性校验或加密功能,请求数据需使用该方法进行封装
SOCKS 请求报文格式如下:
1 |
|
- VER:协议版本,固定为 X’05’
- CMD:命令类型
- RSV:保留字段,必须为 X’00’
- ATYP:目标地址类型
- DST.ADDR:目标地址(根据 ATYP 类型解析)
- DST.PORT:目标端口(2 字节,网络字节序)
Addressing
ATYP 字段
- X’01’:IPv4 地址(长度为 4 字节)
- X’03’:域名(首字节为长度,后面为域名字符串)
- X’04’:IPv6 地址(长度为 16 字节)
Replies
客户端发送完请求并完成认证后,服务器评估请求并返回回复报文:
1 |
|
- VER:协议版本(X’05’)
- REP:回复状态码
- RSV:保留字段,必须为 X’00’
- ATYP:BND.ADDR 的类型
- BND.ADDR:服务器绑定的地址
- BND.PORT:服务器绑定的端口
Procedure for UDP-based clients
原本的UDP 协议并不会对数据进行封装,而是选择发一包就走。Socks协议为了穿越防火墙,就会对这些数据进行封装
基于 UDP 的客户端必须将数据发送至 UDP 中继服务器(UDP relay server),目标端口即为前面 UDP ASSOCIATE 请求的回复中所返回的 BND.PORT
UDP 数据报请求头格式如下:
1 |
|
- RSV(2 字节):保留字段,必须为 0x0000
- FRAG(1 字节):分片编号(fragment number)
- ATYP(1 字节):地址类型
- DST.ADDR:目标地址(根据 ATYP 类型变化)
- DST.PORT:目标端口(2 字节,网络字节序)
- DATA:用户数据
中继服务器的行为:
- 当 UDP 中继服务器决定转发一个datagram时,它不会通知客户端;
- 无法转发的datagram将被静默丢弃;
- 服务器从远程主机收到回复datagram时,必须使用以上格式封装datagram并返回客户端;
- 中继服务器必须事先知道客户端的 IP 地址(通过 TCP 控制连接获得);
- 对于任何非预期来源(即 IP 地址不匹配的客户端)发送的 UDP datagram,必须丢弃。
关于FRAG:
- FRAG 字段用于表示该数据报是否是分片序列的一部分;
- 0x00 表示 非分片独立数据报;
- 值在 1 到 127 之间表示在一个分片序列中的位置;
- 实现必须有一个重组队列(reassembly queue)和重组计时器(reassembly timer)来处理分片;
- 一旦超时或收到更早序号的分片,则必须丢弃当前所有分片;
- 重组计时器的最小时间为5秒;
- 建议尽量避免使用分片;
- 如果不支持分片,收到 FRAG != 0x00 的数据报必须直接丢弃。
关于缓冲区空间报告:
SOCKS 协议中对 UDP 报文进行封装,因此可用的应用层缓冲区比实际系统缓冲区要小:
- ATYP 是 0x01(IPv4) ⇒ 少 10+认证封装 字节;
- ATYP 是 0x03(域名) ⇒ 少 262+认证封装 字节;
- ATYP 是 0x04(IPv6) ⇒ 少 20+认证封装 字节。
也就是说,应用程序可用的 UDP 空间 小于系统提供的实际空间,必须预留封装用头部空间。