SOCKS5 与 SOCKS4 代理
SOCKS 代理让应用可以要求中间服务器代为连接目标。代理打开所请求的连接,并双向传递数据。应用继续使用自己的协议,因此这种方式适用于 Web 请求、API 客户端、文件传输,以及其他支持 SOCKS 的软件。
对于新配置,SOCKS5 通常提供最实用的选项:更多地址格式、可选择的身份验证方法和 UDP 支持。对于要求旧版本的软件,SOCKS4 仍然有用。上述协议与 HTTP 代理之间的整体选择,见SOCKS 与 HTTP 代理。
应用如何通过 SOCKS 连接
假设应用通过 SOCKS5 代理打开 https://example.com/。它先连接代理,请求代理建立到网站的连接,然后才交换网站数据。整个过程分为四个阶段:
- 应用通过 TCP 连接代理的主机名或 IP 及监听端口。
- 应用和代理选择访问方法。如果该方法需要凭据,应用提供凭据,由代理检查。
- 应用发送带目标地址和端口的
SOCKS CONNECT请求。代理检查访问规则、尝试建立后续连接,并报告结果。 - 收到成功响应后,应用通过代理与目标通信。对于 HTTPS 网站,它会先与网站建立 TLS 并验证证书,然后发送 Web 请求。
这两个端口号属于不同服务器。例如,代理可能在 proxy.example:1080 监听,而网站通过 example.com:443 访问。1080 是 SOCKS 的惯用端口,但服务也可以使用其他端口。应使用为你的代理分配的监听端口;它不能替代目标端口。
普通 TCP 转发期间,SOCKS 传递应用的字节流,无需解析每个 HTTP 请求或文件命令。应用继续以自己的协议与目标通信。因此,相同的 SOCKS 连接机制可以服务 Web 客户端和其他类型的软件。
CONNECT 是 SOCKS 内部的命令,有自己的消息格式,与 HTTP CONNECT 方法不同。SOCKS 还定义了 BIND,适用于需要服务器通过代理反向连接的应用,例如主动 FTP 可能采用的方式。BIND 需要单独支持,普通网站或 API 请求不会使用它。
SOCKS4、SOCKS4a 与 SOCKS5 有何区别
SOCKS4 建立到 IPv4 地址的 TCP 连接。SOCKS4a 增加发送主机名的选项,让代理可以通过 DNS 查找其 IP。SOCKS5 增加可选身份验证方法,接受 IPv4 地址、IPv6 地址和主机名,并定义了 UDP 转发。
| 功能 | SOCKS4 | SOCKS4a | SOCKS5 |
|---|---|---|---|
| 出站 TCP 连接 | 支持 | 支持 | 支持 |
| 请求中的目标 | IPv4 地址 | IPv4 地址或域名 | IPv4 地址、IPv6 地址或域名 |
| 代理可以查询主机名 | 不支持 | 支持 | 支持 |
| 标准用户名/密码方法 | 不支持 | 不支持 | 支持 |
| UDP 中继机制 | 不支持 | 不支持 | 支持 |
这些是协议能力。客户端和代理服务必须实现你打算使用的具体功能。例如,SOCKS5 服务可能可以处理 TCP 连接,却不提供可用的 UDP 中继。
SOCKS5 请求可以携带 IPv6 目标,但代理还必须能够访问该 IPv6 服务器。两段连接可以使用不同 IP 版本:应用可能通过 IPv4 连接代理,代理则通过 IPv6 连接目标。
SOCKS4a 是 SOCKS4 的扩展,并不是所有 SOCKS4 连接的另一个名称。如果旧客户端只发送 IPv4 地址,选择 SOCKS4 不会赋予它远程 DNS 能力。SOCKS4a 需要两端支持。如果两端都支持,SOCKS5 通常更简单;选择 SOCKS4 本身不会改善出口 IP 信誉或速度。
谁解析目标名称
连接以名称标识的服务器之前,必须先把名称转换为 IP 地址。SOCKS5 可以接受查询结果,也可以接受名称本身。发送哪一种,由客户端 DNS 设置决定。
使用本地 DNS 时,应用向配置的解析器查询 reports.example。假设结果是 203.0.113.27,应用随后请求建立到 203.0.113.27:443 的 SOCKS 连接。即使后续网站连接经过代理,查询也已经在客户端一侧完成。
使用代理侧 DNS 时,应用直接发送 reports.example:443,不先在本地查询目标。代理通过 DNS 获得 IP,再建立所请求的连接。主机名作为 SOCKS 请求的一部分到达代理。
如果客户端无法解析某个名称,但代理能够解析,这种方式会有帮助。有些服务会根据 DNS 解析器返回不同地址,因此移动查询位置可能改变接收连接的服务器。它不会设置代理出口国家,也不保证网站接受请求。
在 curl 中,下面两条命令分别选择两种 DNS 模式:
curl --proxy socks5://proxy.example:1080 https://example.com/
curl --proxy socks5h://proxy.example:1080 https://example.com/
socks5:// 让 curl 在本地解析网站名称;socks5h:// 则把名称交给代理。两者都使用 SOCKS5。h 在该客户端的 URL 语法中表示由代理解析主机名。它不会把 SOCKS5 变成 HTTPS,也不会增加加密。其他应用可能使用复选框,或自动选择远程 DNS。请将示例代理主机名和端口替换为实际服务信息,并提供所需身份验证。
在 SOCKS5 TCP 请求中传递域名,并不要求支持 UDP 中继。代理按自己的 DNS 配置进行查询。这与要求 SOCKS5 承载客户端 UDP 数据包不同。
如果客户端原本配置为把目标 DNS 交给代理,却在本地执行查询,就会在预期路径之外暴露请求的名称。这就是 DNS 泄漏。加密 DNS 保护与解析器之间的交互,但解析器仍会收到名称。查询代理自身的主机名是另一项任务,其他应用也保留自己的 DNS 行为。一个程序使用远程 DNS,不会转移设备上的每次查询。
身份验证与加密
SOCKS5 允许客户端提供支持的身份验证方法,由代理选择其中一种。用户名和密码是一种选项;另一种是无需 SOCKS 登录交互的连接,服务可能在将客户端源 IP 与允许访问列表核对后放行。因此,没有密码字段的端点,仍可能限制访问。
无法协商出共同方法,与密码被拒绝不同:前一种情况下,密码交互尚未发生。不支持用户名/密码的客户端,即使有 SOCKS5 设置,也无法使用只接受密码验证的 SOCKS5 端点。SOCKS4 有用户 ID 字段,但没有对应的标准密码交互;服务器仍可以实施访问规则。
常规 SOCKS5 用户名/密码交互,不会加密凭据。它发生在应用与目标建立 HTTPS 之前,因此后续 HTTPS 连接不会保护更早的代理登录。加密客户端到代理的路径,需要独立的受保护连接,或明确支持的安全机制。
普通 SOCKS 转发期间,如果启用证书验证且没有 TLS 拦截,HTTPS 会保护应用与网站之间的交互。未加密的应用协议通过中继后,仍然未加密。仅支持 SOCKS5 或密码身份验证,并不承诺流量已加密。
代理仍然知道客户端连接 IP、请求的目标和连接时间。目标看到代理出口 IP,并接收发给自己的应用数据。Cookie、账户登录和其他应用标识,仍可能识别用户;改变 SOCKS 版本不会移除它们。
SOCKS5 如何承载 TCP 和 UDP
TCP 提供有序字节流。如果客户端支持相应路径,而且代理允许目标,浏览器请求、API 调用或 SSH 会话都可以使用 SOCKS TCP 连接。成功连接某个网站的 443 端口,并不能证明另一个应用的端口也可用。
UDP 发送独立数据报。SOCKS5 客户端先打开 TCP 控制连接,通过 UDP ASSOCIATE 请求中继。代理返回中继地址和 UDP 端口。客户端向那里发送数据报,并带有说明目标的 SOCKS 头。关闭 TCP 控制连接,就会结束这个 UDP 关联;数据报与控制连接分开传输,并不位于普通 SOCKS CONNECT 字节流中。
应用和服务都必须支持该机制,网络也必须允许 UDP 路径。程序可能完成 TCP 登录,但语音、游戏或其他 UDP 功能仍然失败。通过 SOCKS CONNECT 成功发出 HTTPS 请求,只能证明 TCP 转发正常,不能证明 UDP 可用。QUIC 使用 UDP,但 QUIC 能否使用,还取决于客户端和完整路径;仅有 SOCKS5 标签不能证明这一点。
SOCKS 适用于哪些场景
软件需要通过中间服务器连接,同时保留自己的应用协议时,SOCKS 就很有用。脚本可以通过已分配出口 IP 请求 API 数据,文件传输客户端可以经批准路径访问远程服务器,兼容的桌面应用也可以在不是浏览器的情况下使用代理。每种场景都取决于客户端 SOCKS 支持,以及服务允许的目标端口。
反复访问同一账户或服务器时,固定出口可能合适;对于独立任务,轮换服务可能有用。SOCKS4 和 SOCKS5 不决定这种行为:出口 IP、网络类型、是否由其他客户使用,以及何时变化,都由服务决定。协议版本也不构成速度排名;路由长度、服务器负载和可用带宽都会影响结果。
客户端支持范围可能小于协议范围。Chrome 内置的 SOCKS5 实现通过代理解析目标名称,但不进行 SOCKS5 用户名/密码验证,也不中继 UDP。因此,只接受密码验证的端点可能在 curl 中正常,却无法通过浏览器内置设置使用。外部适配工具是连接中的独立组成部分,有自己的能力范围。
在一个程序内部配置的代理,只适用于该程序支持的连接,不会配置独立下载器或脚本。系统代理设置同样只影响使用该设置的软件。如果适配工具重定向没有原生 SOCKS 支持的应用连接,它对 TCP、UDP 和 DNS 的覆盖范围就很重要。SOCKS 不提供普通 ICMP 转发,因此 ping 不能测试这条代理路径。
连接设置与有效测试
先使用端点提供的代理地址、监听端口、SOCKS 版本和访问方式。1080 这样的数字本身不能标识协议。应在客户端中选择 SOCKS,而不是把相同地址填入仅支持 HTTP 的代理字段。
代理凭据授权使用中间服务器,网站登录则授权使用网站。两者属于不同设置。在 curl 中,--proxy-user 提供代理凭据,--user 提供目标凭据。对于基于 IP 的访问,允许访问列表必须匹配代理看到的客户端源 IP;客户端更换网络后,这个 IP 可能变化。
选择预期 DNS 模式后,检查所有绕过规则。对于排除列表中的目标,程序可能跳过已配置代理。在 curl 中,NO_PROXY 可能导致这种情况;如果有意测试代理路径,--noproxy "" 可在一次调用中清除这些排除项。
应从实际执行工作的程序测试。IP 检查端点,或你控制的目标服务器日志,可以显示请求源 IP。将结果与直接请求比较。用于连接代理的地址,与目标看到的出口地址,不一定相同。
然后尝试真实任务。IP 改变能证明被测请求的路由,却不能测量所有传输方式,也不能说明另一个网站会如何响应。任务需要 UDP 或 IPv6 时,应单独测试,并在有代表性的负载下评估响应时间和连接稳定性。
按连接阶段定位错误
应区分连接代理、取得访问权、建立目标连接,以及接收应用响应。这些阶段的失败原因不同。
| 失败情况 | 应检查什么 |
|---|---|
| 代理连接超时或被拒绝 | 代理主机名、监听端口、网络可达性和访问限制。此时尚未建立目标连接。 |
| 没有可接受的身份验证方法 | 客户端是否支持该端点接受的方法。这还不是对密码是否正确的判断。 |
| 用户名/密码登录被拒绝 | 确认已选中密码方法后,检查代理凭据和账户访问权限。 |
| 无法解析目标名称 | 由哪一侧执行查询。本地 DNS 错误可能在客户端要求 SOCKS 建立目标连接之前出现。使用远程 DNS 时,代理必须取得目标 IP。 |
| 代理拒绝目标或操作 | 访问规则、目标端口,以及对所请求命令或地址类型的支持。策略拒绝与不支持 UDP 命令或 IPv6 地址是不同情况。 |
| 代理无法连接目标 | 从代理网络检查目标地址、端口和可用性。目标可能不可达,也可能拒绝连接。 |
如果经过验证的 HTTPS 连接成功,网站返回登录页、CAPTCHA 或访问拒绝,说明 SOCKS 连接已经承载了这次交互。应调查网站响应和应用行为。如果请求显示的反而是你平常的公网 IP,应检查该程序所选代理和绕过规则。
