# node-socks5 **Repository Path**: yhding/node-socks5 ## Basic Information - **Project Name**: node-socks5 - **Description**: 简单node实现一个socks5协议,还没完成 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-01-02 - **Last Updated**: 2023-02-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # socks5相关实现 ## socks5建立连接的过程 > 除非特别说明,包结构图里面的十进制数字代表该字段的长度(`byte`数)。 > 给定的字段,必定要有确定的值,语法 `x‘hh’` 代表该字段的值。 > `Variable` 代表该字段为可变长度,其长度要么由对应的关联字段标识(通常`1-2`个`byte`),要么由数据类型确定。 ### 1. 客户端发送协议版本与认证方法。 | VER(版本) | NMETHODS(方法数量) | METHODS(方法列表) | | --------- | ------------------ | ----------------- | | 1 | 1 | 1 to 255 | ### 2. 服务端选择一个认证方法返回。 | VER(版本) | METHOD(选定的方法识别码) | | --------- | ------------------------ | | 1 | 1 | 如果 `method` 字段是 `X’FF‘` 表示方法列表中的所有方法均不可用,客户端收到此信号必须关闭连接。 目前可用的方法: - x'00' 无需认证 - x'01' GSSAPI - x'02' 用户名/密码 - x'03'~x'7F' IANA指定 - x'03'~x'FE' 为私有方法保留 - x'FF' 无方法可接受 客户端与服务端开始协商该方法对应的后续认证,后续认证方法因方法而异,在单独的文档里面进行描述。 为本协议开发新方法的开发者需要到 `IANA` 组织申请一个方法编号。被授予编号的方法的对应文档,会列在方法编号列表,对应协议版本的文档中呈现。 认证完成。 ### 3. 客户端发送请求细节 如果认证方法为了完整性或者可信性的校验,需要对后续请求报文进行封装,则后续请求报文都要按照对应的规定进行封装。 请求格式如下: | VER(版本) | CMD(命令) | RSV(保留字段) | ATYP(地址类型) | DST.ADDR(目标地址) | DST.PORT(目标端口,网络字节序) | | --------- | --------- | ------------- | -------------- | ------------------ | ------------------------------ | | 1 | 1 | x'00' | 1 | Variable | 2 | - VER 协议版本: `X‘05’` - CMD 命令 - CONNECT 连接, `X‘01’` - BIND 监听`X‘02'` - UDP `ASSOCIATE` UDP关联 `X‘03’` - RSV 保留字段 - ATYP 地址类型 - IPV4 `X‘01’` - 表明地址字段为一个`IPV4`地址,长度为`4字节` - 域名 `X‘03’` - 表示地址字段是一个合法的域名,且第一个字节为域名长度标识,显然其不为null作为结束标志。 - IPV6 `X‘04’` - 表示地址字段为一个`IPV6`地址,长度为`16字节` - DST.ADDR 目标地址 - DST.PORT 目标端口 (网络字节序) SOCKS 服务端会根据请求类型和源、目标地址,执行对应操作,并且返回对应的一个或多个报文信息。 ### 4. 服务端回复报文 客户端与服务端建立连接并完成认证之后就会发送请求信息,服务端执行对应请求并返回如下格式的报文: | VER(版本) | REP(回复类型) | RSV(保留字段) | ATYP(地址类型) | BND.ADDR(服务端绑定地址) | BND.PORT(服务端绑定端口,网络字节序) | | --------- | ------------- | ------------- | -------------- | ------------------------ | ------------------------------------ | | 1 | 1 | x'00' | 1 | Variable | 2 | - VER协议版本: X‘05’ - REP 回复字段(回复类型): - X‘00’ 成功 - X‘01’ 常规 SOCKS 服务故障 - X‘02’ 规则不允许的连接 - X‘03’ 网络不可达 - X‘04’ 主机无法访问 - X‘05’ 拒绝连接 - X‘06’ 连接超时 - X‘07’ 不支持的命令 - X‘08’ 不支持的地址类型 - X‘09’ 到 X’FF’ 未定义 - RSV 保留字段 - ATYP 地址类型 - IPV4 X‘01’ - 域名 X‘03’ - IPV6 X‘04’ - BND.ADDR 服务端绑定地址 - BND.PORT 服务端绑定端口 (网络字节序) 其中,标记为保留字段( RSV )的值必须设定为 X‘00’ 。 如果协商的方法为了完整性、可信性的校验需要封装数据包,则返回的数据包也会进行对应的封装。 - 连接(connect) 服务端回复报文中 `BND.*` 为 `服务端`用来连接目标的地址所使用的 `BND.ADDR: ip`和`BND.PORT: 端口`。 > `BND.ADDR: IP` 一般与客户端连接的`socks`服务端地址不同,此类服务往往十多台机器提供服务。`socks` 服务端会使用目标地址、端口和客户端源地址、源端口来执行连接请求(建立对应关系)。 - 绑定(BIND) 应用协议客户端应当在通过连接命令建立主要连接后,再通过绑定命令建立第二个连接。`SOCKS` 服务端应当根据 `DST.ADDR` 和 `DST.PORT` 来执行绑定命令。 - UDP 关联 (UDP ASSOCIATE) - 回复处理 当回复报文表明请求失败时( REP 字段为非 X‘00’ ), SOCKS 服务端必须在发送该返回报文后及时关闭 TCP 连接。整个过程应当在确认当前状态的确发生故障后的 10s 内完成。 如果返回报文表明请求成功 ( REP 字段为 X‘00’ )且对应的请求指令为绑定( BIND )或者连接( CONNECT ),则客户端应当立刻开始进行数据传输。 ## 基于 UDP 的客户端处理过程 基于 UDP 的客户端应当把 UDP 报文发送到 UDP 关联回复报文所指定的中继服务地址和端口。 | RSV(保留字段) | FRAG(当前帧序号) | ATYP(地址类型) | DST.ADDR(目的地址) | DST.PORT(目的端口) | DATA(数据) | | ------------- | ---------------- | -------------- | ------------------ | ------------------ | ---------- | | 2 | 1 | 1 | Variable | 2 | Variable | - RSV 保留字段,应当置为 X‘0000’ - FRAG 当前帧序号 - ATYP 地址类型 - IPV4 X‘01’ - 域名 X‘03’ - IPV6 X‘04’ - DST.ADDR 目的地址 - DST.PORT 目的端口 - DATA 用户数据 当一个 UDP 中继服务决定中继一个 UDP 报文时,其是如此静默,不会给客户端任何反馈。类似地,不会或不能被中继的数据包会被丢弃。当中继服务收到了外部主机的 UDP 回复报文时,中继程序必须对应补充上述请求头,并按照协商的认证方法所对应的封装方法对数据进行封装。 参考 - [RFC 1928 - SOCKS 5 协议中文文档「译」](https://www.quarkay.com/code/383/socks5-protocol-rfc-chinese-traslation) - [SOCKS 5 协议抓包分析](https://www.quarkay.com/code/394/SOCKS5-protocol-wireshark-capture-analysis) - socks5实现服务端 https://www.npmjs.com/package/socksv5 - 网络异常抓包 https://help.aliyun.com/document_detail/40564.html - [三百行代码搭建一个简单的 SOCKS5 代理服务器](https://huoyijie.cn/article/43d8648090fe11ebafa22393c04133cd/)