Proxy

Proxy Server 代理服务器

Basic

  • Define:代理服务器是位于客户端和目标服务器之间的中间服务器。
  • Func:隐藏真实IP、加速访问、访问限制内容、过滤内容

Socket Secure 5

  • Socks5 是一个万能的中间人代理协议,可以绕过防火墙、隐藏 IP、访问受限内容,并支持更广泛的网络应用
  • 支持 TCP 和 UDP,比 HTTP 代理更强大
  • TCP:传输控制协议(可靠但慢)三次握手协议 ACK数据确认 belike 打电话
  • UDP:用户数据报协议(快但不可靠)不建立连接,直接“扔包” belike 发短信
  • 本协议旨在为基于 TCP 和 UDP 的客户端-服务器应用程序提供一种方便且安全地使用防火墙服务的机制
  • 介于应用层与传输层之间的“中间层”

代理客户端

在我们的简单代理服务器中, 用户请求的所有流量都会直接从服务器所在的机器发出:

1
2
3
+---------+   +--------------+   +----------+
| User ->-+---+-> Proxy 1 ->-+---+-> Server |
+---------+ +--------------+ +----------+

你也可以让流量经过另一台 socks5 代理服务器:

1
2
3
+---------+   +--------------+   +--------------+   +----------+
| User ->-+---+-> Proxy 1 ->-+---+-> Proxy 2 ->-+---+-> Server |
+---------+ +--------------+ +--------------+ +----------+

为此, 你需要在 Proxy 1 上实现一个 socks5 代理客户端。这个客户端会将 socks5 请求重新包装成 socks5 请求并发送给 Proxy 2。

Procedure for TCP-based Clients

当一个基于 TCP 的客户端希望建立连接,而目标对象只能通过防火墙访问(具体如何判断由实现决定),它必须向 SOCKS 服务器的指定端口(默认是 TCP 端口 1080)建立一个 TCP 连接。

如果连接成功,客户端接下来将发起 认证方法协商,完成认证过程后发送中继请求。SOCKS 服务器评估请求,然后决定是否建立连接或拒绝请求。

客户端首先向服务器发送一个“版本标识/方法选择”报文:

1
2
3
4
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 到 255 |

rmk:这是字节数

  • VER:设置为 X’05’,表示协议版本 5;
  • NMETHODS:表示 METHODS 字段中包含的认证方法数量;
  • METHODS:列出客户端支持的认证方法。

服务器收到后,从 METHODS 中选择一种方法,并返回如下回应:

1
2
3
4
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |

请求格式

一旦方法协商完成,客户端发送具体请求。若认证方法提供完整性校验或加密功能,请求数据需使用该方法进行封装
SOCKS 请求报文格式如下:

1
2
3
4
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00'| 1 | Variable | 2 |
  • 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
2
3
4
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
  • 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
2
3
4
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
  • 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 空间 小于系统提供的实际空间,必须预留封装用头部空间。


Proxy
https://janezair.site/2025/07/15/Proxy/
Author
Yihan Zhu
Posted on
July 15, 2025
Updated on
July 15, 2025
Licensed under