SOCKS4a 代理
什么是 SOCKS4a
SOCKS4a 是 SOCKS4 协议的扩展,由 Ying-Da Lee 提出。与原始 SOCKS4 的关键区别在于,客户端可以发送域名而不是 IP 地址,DNS 解析在代理服务器一侧完成。
在标准 SOCKS4 中,客户端必须先自行把域名解析为 IP 地址,然后才能发送请求。这带来一个问题:DNS 查询直接从客户端发出,暴露了所访问网站的信息。SOCKS4a 解决了这一问题。
SOCKS4 的 DNS 问题
SOCKS4 的工作方式
- 客户端想连接 example.com
- 客户端直接发起 DNS 查询(不经过代理)
- 得到 IP 93.184.216.34
- 向代理发送命令:"连接到 93.184.216.34:80"
- 代理建立 TCP 连接
问题:第 2 步的 DNS 查询对 ISP、DNS 服务器以及任何监听流量的人都是可见的。这就是 DNS 泄漏。
SOCKS4a 的工作方式
- 客户端想连接 example.com
- 客户端向代理发送命令:"连接到 example.com:80"
- 代理自己把 example.com 解析为 IP
- 代理建立 TCP 连接
DNS 查询完全隐藏在代理之后。
技术实现
SOCKS4 请求格式
| 字段 | 长度 | 说明 |
|---|---|---|
| VER | 1 字节 | 版本(0x04) |
| CMD | 1 字节 | 命令(0x01 = CONNECT) |
| DSTPORT | 2 字节 | 目标端口 |
| DSTIP | 4 字节 | 目标 IP |
| USERID | 可变 | 标识字符串 |
| NULL | 1 字节 | 0x00(终止符) |
SOCKS4a 请求格式
格式相同,但用了一个技巧:DSTIP 字段填入形如 0.0.0.x 的无效 IP(其中 x > 0)。在 USERID 的 NULL 终止符之后追加域名:
| 字段 | 长度 | 说明 |
|---|---|---|
| VER | 1 字节 | 0x04 |
| CMD | 1 字节 | 0x01 |
| DSTPORT | 2 字节 | 目标端口 |
| DSTIP | 4 字节 | 0.0.0.1(SOCKS4a 标记) |
| USERID | 可变 | 标识字符串 |
| NULL | 1 字节 | 0x00 |
| DOMAIN | 可变 | 域名(example.com) |
| NULL | 1 字节 | 0x00 |
代理看到形如 0.0.0.x 的 IP,就知道 USERID 之后还有一个待解析的域名。
SOCKS4 与 SOCKS4a、SOCKS5 对比
| 参数 | SOCKS4 | SOCKS4a | SOCKS5 |
|---|---|---|---|
| 代理侧 DNS | 否 | 是 | 是 |
| 身份验证 | 否 | 否 | 是 |
| UDP | 否 | 否 | 是 |
| IPv6 | 否 | 否 | 是 |
| BIND 命令 | 是 | 是 | 是 |
| ASSOCIATE 命令 | 否 | 否 | 是 |
SOCKS4a 的优点
1. 消除 DNS 泄漏
主要优点是客户端不再直接发起 DNS 查询。所有 DNS 活动都隐藏在代理之后。
2. 协议简单
SOCKS4a 比 SOCKS5 更易实现。没有身份验证阶段,也不支持 UDP——只有 TCP CONNECT。
3. 向后兼容
SOCKS4a 客户端可以与 SOCKS4a 代理配合工作,且请求格式向后兼容 SOCKS4。
4. 访问 .onion 和内部域名
由于 DNS 在代理侧解析,SOCKS4a 可用于访问公共 DNS 无法解析的域名(例如通过 Tor 访问 .onion)。
局限
1. 无身份验证
SOCKS4a 不支持身份验证。任何知道代理地址的人都可以使用它。
2. 不支持 UDP
仅支持 TCP 连接。经由 UDP 的 DNS 查询、VoIP 和游戏流量都不受支持。
3. 不支持 IPv6
DSTIP 字段为 4 字节,仅适用于 IPv4。
4. 协议已过时
SOCKS5 取代了 SOCKS4a,提供其全部能力并增加了身份验证、UDP 和 IPv6。
何时使用 SOCKS4a
- 遗留系统 —— 不支持 SOCKS5 的老旧软件
- 简单场景 —— 不需要身份验证和 UDP 时
- Tor 连接 —— Tor 支持用 SOCKS4a 解析 .onion
- 最小开销 —— 需要协议延迟尽可能低时
软件支持
| 程序 | SOCKS4a |
|---|---|
| curl | 支持(--socks4a) |
| Tor | 支持(主要协议) |
| ProxyChains | 支持 |
| Firefox | 通过 network.proxy.socks_remote_dns |
| PuTTY | 支持 |
结论
SOCKS4a 解决了 DNS 泄漏问题,是从 SOCKS4 演进而来的重要一步。尽管如今的标准是 SOCKS5,但理解 SOCKS4a 对处理遗留系统以及理解代理协议的演进仍然有用。
