SOCKS5 通信协议与通信流程
2026/5/4 6:02:14 网站建设 项目流程

一、SOCKS5 协议概述

SOCKS(Socket Secure)是一种网络代理协议,主要用于在客户端和服务器之间安全地传输数据。SOCKS5 是其第五个版本,在 RFC 1928 中定义。它相比前代版本增加了对 UDP 协议的支持、多种认证方式以及 IPv6 地址的支持。

主要特点:

  • 支持 TCP 和 UDP 协议代理
  • 支持多种认证方式(无认证、用户名/密码、GSS-API 等)
  • 支持 IPv4、IPv6 和域名地址类型
  • 工作在会话层(第 5 层),不解析应用层协议
  • 通用性强,可代理 HTTP、HTTPS、FTP、SMTP 等多种协议

二、SOCKS5 通信流程

SOCKS5 通信分为三个阶段:握手阶段认证阶段(可选)、连接请求阶段数据传输阶段

阶段 1:握手和协商认证方式

客户端发送握手包,告诉服务器它支持哪些认证方法:

请求格式:

+----+----------+----------+ |VER | NMETHODS | METHODS | +----+----------+----------+ | 1 | 1 | 1-255 | +----+----------+----------+
  • VER:SOCKS 版本号,固定为0x05
  • NMETHODS:客户端支持的认证方法数量
  • METHODS:支持的认证方法列表

常用认证方法代码:

  • 0x00:无需认证
  • 0x01:GSSAPI
  • 0x02:用户名/密码认证
  • 0x03-0x7F:IANA 分配
  • 0x80-0xFE:私有方法保留
  • 0xFF:无可接受的方法

服务器响应格式:

+----+--------+ |VER | METHOD | +----+--------+ | 1 | 1 | +----+--------+
  • VER0x05
  • METHOD:选中的认证方法(0xFF表示无合适方法)

示例:

客户端发送:[0x05, 0x02, 0x00, 0x02] // 支持无认证和用户名/密码 服务器响应:[0x05, 0x00] // 选择无认证
阶段 2:认证(如果需要)

如果选择了用户名/密码认证(0x02),则进行此步骤(RFC 1929):

客户端认证请求:

+----+------+----------+------+----------+ |VER | ULEN | UNAME | PLEN | PASSWD | +----+------+----------+------+----------+ | 1 | 1 | 1-255 | 1 | 1-255 | +----+------+----------+------+----------+
  • VER:认证版本,固定为0x01
  • ULEN:用户名字段长度
  • UNAME:用户名(UTF-8 编码)
  • PLEN:密码字段长度
  • PASSWD:密码

服务器认证响应:

+----+--------+ |VER | STATUS | +----+--------+ | 1 | 1 | +----+--------+
  • VER0x01
  • STATUS0x00成功,0x01失败
阶段 3:连接请求

客户端发送目标地址和端口信息,请求代理服务器建立连接:

请求格式:

+----+-----+-------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | 0x00 | 1 | 可变 | 2 | +----+-----+-------+------+----------+----------+
  • VER0x05
  • CMD:命令类型
    • 0x01:CONNECT - 建立 TCP 连接
    • 0x02:BIND - 绑定端口(用于 FTP 被动模式等)
    • 0x03:UDP ASSOCIATE - UDP 关联
  • RSV:保留字段,固定0x00
  • ATYP:地址类型
    • 0x01:IPv4 地址(4 字节)
    • 0x03:域名地址(首字节为域名长度,后跟域名)
    • 0x04:IPv6 地址(16 字节)
  • DST.ADDR:目标地址
  • DST.PORT:目标端口(网络字节序)
请求连接 www.example.com:80 ATYP=0x03,域名长度=11,域名="www.example.com"(11字节) DST.PORT=0x0050(80) 数据包:[0x05, 0x01, 0x00, 0x03, 0x0B, 'w','w','w','.','e','x','a','m','p','l','e','.','c','o','m', 0x00, 0x50]
阶段 4:连接响应

服务器返回连接结果:

响应格式:

+----+-----+-------+------+----------+----------+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | 0x00 | 1 | 可变 | 2 | +----+-----+-------+------+----------+----------+
  • VER0x05
  • REP:响应代码
    • 0x00:成功
    • 0x01:一般 SOCKS 服务器错误
    • 0x02:连接规则不允许
    • 0x03:网络不可达
    • 0x04:主机不可达
    • 0x05:连接被拒绝
    • 0x06:TTL 超时
    • 0x07:不支持的命令
    • 0x08:不支持的地址类型
    • 0x09-0xFF:未分配
  • RSV:保留字段,固定0x00
  • ATYP:绑定地址类型
  • BND.ADDR:服务器绑定的地址
  • BND.PORT:服务器绑定的端口
阶段 5:数据传输

连接建立成功后,代理服务器在客户端和目标服务器之间透明转发数据。对于 TCP CONNECT,后续所有数据直接通过代理隧道传输,不需要额外封装。


三、UDP ASSOCIATE 流程

UDP 代理相对复杂,需要先通过 TCP 建立 UDP 关联:

  1. 客户端发送 UDP ASSOCIATE 命令(CMD=0x03)
  2. 服务器返回绑定的 UDP 端口和地址
  3. 客户端发送 UDP 数据报:

SOCKS5 的 UDP 代理与 TCP 代理有本质区别。UDP 是无连接协议,因此需要先通过 TCP 控制连接建立一个"UDP 关联",然后才能通过 UDP 协议传输数据。

阶段 1:建立 UDP 关联(通过 TCP 控制连接)

客户端必须先通过TCP 连接向代理服务器发送 UDP ASSOCIATE 请求:

请求格式(与 TCP CONNECT 相同):

+----+------+------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+------+------+------+----------+----------+ | 1 | 0x03 | 0x00 | 1 | 可变 | 2 | +----+------+------+------+----------+----------+
  • VER:0x05
  • CMD:0x03(UDP ASSOCIATE)
  • ATYPDST.ADDRDST.PORT:通常设为 0(表示由代理指定端口)
[0x05, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

表示:SOCKS5 + UDP关联 + IPv4地址0.0.0.0 + 端口0

服务器响应(通过同一 TCP 连接返回):

+----+------+------+------+----------+----------+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | +----+------+------+------+----------+----------+ | 1 | 0x00 | 0x00 | 1 | 可变 | 2 | +----+------+------+------+----------+----------+
  • BND.ADDR:代理服务器分配的 UDP 地址
  • BND.PORT:代理服务器分配的 UDP 端口(客户端后续向此地址发 UDP)

重要:建立 UDP 关联的 TCP 连接必须保持打开状态,直到 UDP 代理结束。关闭该 TCP 连接会自动终止 UDP 关联。


阶段 2:UDP 数据报封装格式

所有通过代理发送的 UDP 数据报都必须按照 RFC 1928 定义的特殊格式封装:

UDP 数据报封装格式:

+----+------+------+----------+----------+----------+ |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | +----+------+------+----------+----------+----------+ | 2 | 1 | 1 | 可变 | 2 | 可变 | +----+------+------+----------+----------+----------+
字段大小说明
RSV2 字节保留字段,必须为0x0000
FRAG1 字节分片编号(见下文分片说明)
ATYP1 字节地址类型(0x01=IPv4, 0x03=域名, 0x04=IPv6)
DST.ADDR可变目标地址(真正的最终接收方)
DST.PORT2 字节目标端口
DATA可变实际应用数据

封装示例:

原始数据:客户端想发送 "HELLO" 到 192.168.1.100:8888 封装后:[0x00, 0x00, 0x00, 0x01, 192,168,1,100, 0x22, 0xB8, 'H','E','L','L','O'] [ RSV=0 ] [FRAG=0] [IPv4] [ 目标IP地址 ] [端口8888] [ 数据 ]

阶段 3:UDP 数据发送与接收

发送流程(客户端 → 代理 → 目标服务器):

  1. 客户端按封装格式打包 UDP 数据报
  2. 客户端将封装后的数据报发送到代理服务器的 UDP 端口(阶段1获取的 BND.ADDR:BND.PORT)
  3. 代理服务器解封装,提取 DST.ADDR、DST.PORT 和 DATA
  4. 代理服务器将原始 DATA 作为 UDP 负载发送到真正的目标服务器

接收流程(目标服务器 → 代理 → 客户端):

  1. 目标服务器返回 UDP 响应数据到代理服务器
  2. 代理服务器记录响应的源地址和端口
  3. 代理服务器按封装格式打包响应:
    1. DST.ADDR/DST.PORT 替换为响应来源的地址(即真正的目标服务器)
    2. DATA 为响应数据
  4. 代理服务器将封装后的数据报发送给客户端

三、分片机制(FRAG 字段)

重要说明:当前几乎所有实现都简单地将FRAG设为 0,不支持分片。分片机制在设计上存在但实际已废弃。

FRAG 值含义
0完整的数据报,或最后一个分片
1-127分片编号(非最后一个分片)

设计原理(实际很少使用):

  • 当 UDP 数据报过大,需要分片传输时使用
  • 代理服务器负责重组分片后再转发
  • 收到 FRAG=0 的数据报时,表示之前的分片(如果有)已完整接收

实际现状:由于 UDP 数据报通常较小(< 1472 字节),且现代网络 MTU 足够,几乎没有代理实现分片功能。客户端应避免发送超大 UDP 包。

四、完整示例:DNS over SOCKS5 UDP

这是一个实际场景:客户端通过 UDP 代理查询 DNS(目标 8.8.8.8:53)

步骤 1:建立 TCP 控制连接

客户端 → 代理: TCP 连接 192.168.1.100:1080 客户端 → 代理: [0x05, 0x01, 0x00] (握手:只支持无认证) 代理 → 客户端: [0x05, 0x00] (握手响应:选择无认证) 客户端 → 代理: [0x05, 0x03, 0x00, 0x01, 0x00,0x00,0x00,0x00, 0x00,0x00] (UDP关联) 代理 → 客户端: [0x05, 0x00, 0x00, 0x01, 192,168,1,100, 0x42,0x34] (绑定 0.0.0.0:16948)

步骤 2:发送 DNS 查询(UDP)

客户端 → 代理(16948): 封装后的 UDP 数据报 原始 DNS 查询包: [0xAA,0xBB, 0x01,0x00, 0x00,0x01, ...] (假设包长 32 字节) 封装后: [0x00,0x00] // RSV [0x00] // FRAG=0 [0x01] // ATYP=IPv4 [0x08,0x08,0x08,0x08] // 目标地址 8.8.8.8 [0x00,0x35] // 目标端口 53 [0xAA,0xBB,0x01,0x00...] // 原始 DNS 数据(32字节)

步骤 3:接收 DNS 响应

代理(16948) → 客户端: 封装后的响应 代理返回: [0x00,0x00] // RSV [0x00] // FRAG=0 [0x01] // ATYP=IPv4 [0x08,0x08,0x08,0x08] // 源地址 8.8.8.8 (响应来源) [0x00,0x35] // 源端口 53 [0xAA,0xBB,0x81,0x80...] // DNS 响应数据

五、UDP 代理的关键注意事项

问题说明解决方案
来源验证代理可能只接受来自建立关联的 TCP 连接相同 IP:Port 的 UDP确保 UDP 包从同一个源 IP:Port 发送
TCP 关联生命周期关闭 TCP 控制连接 → UDP 关联立即终止保持 TCP 控制连接打开直到不需要 UDP 代理
端口重用多个 UDP 关联不能共享同一个源端口代理服务器为每个 TCP 连接分配唯一的 UDP 端口
UDP 超时长时间无 UDP 流量 → 代理可能关闭关联实现心跳机制或定期发送keepalive包
FRAG 分片大多数代理不支持避免发送超过 1400 字节的 UDP 数据包

六、与 TCP CONNECT 的主要区别

特性TCP CONNECTUDP ASSOCIATE
协议类型面向连接无连接
控制连接建立后传输数据仅用于建立关联
数据路径通过 TCP 连接传输UDP 独立传输
数据封装无需封装必须按 RFC 1928 封装
分片支持自动处理FRAG 字段(已废弃)
生命周期数据传输完关闭显式关闭 TCP 控制连接

七、SOCKS5 的优点与局限

优点:

  • 协议简单,性能开销小
  • 支持多种应用层协议
  • 不限于 HTTP,可用于 SSH、数据库连接等
  • 支持 UDP 协议(如 DNS、VoIP、在线游戏)

局限:

  • 不加密数据(除非配合 TLS,即 SOCKS5 over TLS)
  • 不提供认证信息的加密保护(用户名/密码明文传输)
  • 不支持服务器主动推送连接(需要客户端轮询或长连接)

八、实际应用场景

  • 突破网络限制:访问被防火墙限制的资源
  • 隐私保护:隐藏真实 IP 地址
  • 网络调试:捕获和分析应用层流量
  • 负载均衡:将流量分发到多个后端服务器
  • 企业内网访问:安全地访问内部资源

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询