Skip to content
文章 / 3 分钟阅读

轮换代理网关:为您的整个代理池提供一个本地 SOCKS5 或 HTTP 端点

将每个工具指向一个本地 SOCKS5 或 HTTP 端点,让一个小型网关服务为每个连接选择一个上游代理——附带配置、粘性会话、健康检查、DNS 和泄漏验证。

轮换代理网关:为您的整个代理池提供一个本地 SOCKS5 或 HTTP 端点

在代码内部轮换代理可以正常工作,直到第二个工具出现。现在你有一个带中间件的爬虫、一个手动操作的浏览器、一个只有一个代理字段的 CLI 排名检查器,以及一个别人写的 cron 任务——每个都以自己的方式轮换,或者根本不轮换。

轮换代理网关消除了这种重复。你在本地(或 VPS 上)运行一个小型服务,将所有内容指向 127.0.0.1:8080,网关会为每个连接选择一个上游代理。本指南涵盖该服务是什么、何时值得额外一跳、如何用可读的配置构建一个,以及如何在对生产工作信任它之前验证轮换、DNS 解析和泄漏行为。

轮换代理网关到底是什么

它是代理的负载均衡器。请求路径如下:

  1. 客户端 — 浏览器、curl、Scrapy、Selenium、桌面应用
  2. 网关 — 你机器上的本地 HTTP 或 SOCKS5 监听器
  3. 选择 — 网关从你的池中挑选一个上游
  4. 出口节点 — 上游代理发出出站请求
  5. 目标站点 — 看到出口节点的 IP,而不是你的

网关不会让代理更快、更私密或更可靠。它集中了选择、凭证和健康,这与客户端轮换解决的问题不同。

何时网关优于在代码内部轮换

在以下情况下使用网关:

  • 多个工具需要代理,而其中只有部分原生支持轮换
  • 当提供商轮换你的密码或端口时,你希望有一个地方更新凭证
  • 你需要为登录流程提供粘性会话,同时为爬取提供按请求轮换
  • 你希望有一个单一位置来运行健康检查、封禁检测和上游评分
  • 你希望跨客户端保持一致的 DNS 行为,而不是每个库的怪癖
  • 之后你可能将工作负载从笔记本电脑移到 VPS 或 CI 运行器

在以下情况下跳过网关:

  • 你只有一个客户端,并且它已经有很好的中间件(例如 Scrapy 的轮换代理中间件)
  • 轮换取决于每个请求的业务规则——地理目标、账户、价格层级
  • 你需要所用确切上游的按请求延迟和失败统计,而你的网关没有暴露这些

额外一跳会带来一点延迟。对于大多数自动化来说,与出口节点自身的响应时间相比,这只是一个舍入误差。

首先选择监听器协议

监听器 客户端支持 认证 DNS 行为 注意事项
HTTP (CONNECT) 几乎通用,包括只有“HTTP 代理”字段的应用 基本认证被广泛支持 取决于上游连接器 明文 HTTP 请求在网关处可读;一些工具发送绝对 URL
SOCKS5 浏览器通过各种标志、curl、大多数爬虫和 CLI 工具 用户名/密码(RFC 1929) 主机名可以转发到上游进行远程解析 iOS 和 Android 上的系统代理对话框没有 SOCKS5 选项

如果不确定,在同一个池上运行两个监听器,使用两个端口。除了多一个配置块,没有任何损失。

一个 DNS 细节比人们预期的更重要。如果网关自己解析目标主机名,那么地理准确的结果反映的是网关的解析器,而不是出口节点的位置。将主机名传递到下游——socks5h 风格的行为——将解析保留在出口节点,这对于位置敏感的数据正是你想要的。

使用 gost 构建一个

gost 是一个单一的 Go 二进制文件,支持 HTTP、SOCKS5,并且可以链式连接或平衡上游节点列表。版本很重要:v3 系列使用 YAML 配置文件,而旧版本依赖命令行标志。首先确认你拥有什么。

curl -s https://api.github.com/repos/go-gost/gost/releases/latest | grep tag_name
gost -V

以下是一个最小轮换设置,包含两个上游 SOCKS5 出口,同时暴露为 HTTP 和 SOCKS5 监听器:

services:
  - name: pool-http
    addr: \":8080\"
    handler:
      type: http
      chain: pool
    listener:
      type: tcp

  - name: pool-socks
    addr: \":1080\"
    handler:
      type: socks5
      chain: pool
    listener:
      type: tcp

chains:
  - name: pool
    hops:
      - name: hop-0
        selector:
          strategy: round
        nodes:
          - name: exit-a
            addr: 203.0.113.10:1080
            connector:
              type: socks5
              metadata:
                username: user
                password: pass
          - name: exit-b
            addr: 203.0.113.11:1080
            connector:
              type: socks5
              metadata:
                username: user
                password: pass

测试时在前台运行:

gost -C /etc/gost/gateway.yaml

不同构建版本的选择策略不同——round 按顺序循环节点,一些版本添加随机或基于哈希的选择。检查你的确切版本的 selector 文档,而不是假设某个策略名称存在;如果你需要的功能缺失,下一节中的按策略分配端口的技巧通常也能让你达到目的。

对于任何长期运行的东西,unit 文件胜过一个终端窗口:

[Unit]
Description=Rotating proxy gateway
After=network-online.target

[Service]
ExecStart=/usr/local/bin/gost -C /etc/gost/gateway.yaml
Restart=on-failure
User=gost
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

无需特殊功能的粘性会话

许多任务需要与轮换相反的东西:结账流程、经过身份验证的仪表板或多步表单需要在几分钟内使用相同的出口 IP。与其追求粘性会话标志,不如针对两条链运行两个监听器——一个平衡,一个固定。

services:
  - name: pool-http
    addr: \":8080\"
    handler:
      type: http
      chain: pool
    listener:
      type: tcp

  - name: pinned-http
    addr: \":8081\"
    handler:
      type: http
      chain: pinned
    listener:
      type: tcp

chains:
  - name: pool
    hops:
      - name: hop-0
        selector:
          strategy: round
        nodes:
          - name: exit-a
            addr: 203.0.113.10:1080
            connector:
              type: socks5
          - name: exit-b
            addr: 203.0.113.11:1080
            connector:
              type: socks5

  - name: pinned
    hops:
      - name: hop-0
        nodes:
          - name: exit-a
            addr: 203.0.113.10:1080
            connector:
              type: socks5

端口 8080 为爬取而轮换,端口 8081 为一个出口保持用于会话工作。要固定不同的出口,更改一个地址并重新加载。同样的模式为排名跟踪提供按国家/地区的网关:每个目标国家/地区一个端口,每个端口固定到该国家/地区的出口。

验证轮换、DNS 和泄漏

永远不要假设网关正在执行配置所说的内容。两分钟的验证可以节省一周的混乱数据。

从针对 HTTP 监听器的 shell 循环开始:

for i in 1 2 3 4 5; do
  curl -s --max-time 15 --proxy http://127.0.0.1:8080 https://api.ipify.org?format=json
  echo
done

五次运行应该显示不止一个出口 IP。如果每一行都相同,那么你的选择器没有轮换,或者你只有一个健康的节点。

然后从你实际使用的客户端库确认同样的事情:

import requests

GATEWAY = \"http://127.0.0.1:8080\"
proxies = {\"http\": GATEWAY, \"https\": GATEWAY}

for i in range(5):
    r = requests.get(
        \"https://www.cloudflare.com/cdn-cgi/trace\",
        proxies=proxies,
        timeout=20,
    )
    trace = dict(line.split(\"=\", 1) for line in r.text.strip().splitlines())
    print(i, trace.get(\"ip\"), trace.get(\"loc\"))

loc 字段告诉你 Cloudflare 看到请求来自哪个国家/地区——有助于发现悄悄在本地解析 DNS 并将流量落到错误区域的网关。

对于 SOCKS5 监听器,特意比较两种主机名形式:

curl -s --proxy socks5h://127.0.0.1:1080 https://api.ipify.org
curl -s --proxy socks5://127.0.0.1:1080 https://api.ipify.org

两者都应该能访问互联网;区别在于主机名还是解析后的地址传输到出口节点。对于地理敏感的工作,远程解析是你想要的,并且需要端到端支持——网关和上游都支持。

一个简短的泄漏检查清单:

  • 任何响应都不应显示你的真实 ISP 分配的 IP
  • 重复运行应显示变化(对于固定端口,则是故意的常量)
  • 地理字段应与你配置的池匹配,而不是你自己的位置
  • 基于浏览器的测试需要单独的 WebRTC 和 DNS 检查——网关无法修复 WebRTC 泄漏
  • 经过认证的上游应该大声失败,而不是静默回退到直接连接

运维:加固、健康检查以及关于限制的诚实

一个能工作的网关很容易。一个安全的网关需要一些额外的决策:

  • 默认绑定到 127.0.0.1。在 0.0.0.0 上的未认证代理一旦防火墙出现漏洞,就会成为开放中继。
  • 如果你的构建支持监听器认证,请打开它。如果不支持,通过 SSH 隧道访问网关,而不是暴露端口。
  • 将凭证保存在一个具有严格权限的文件中,不要分散在脚本中。
  • 添加日志轮换,如果流量涉及任何敏感内容,在记录完整 URL 之前要三思。
  • 记住网关不会增加容量。你的上游池的并发限制仍然是上限。

一个简单的健康检查胜过聪明的健康检查。此脚本标记失效的上游,以便你可以从配置中移除它们:

#!/usr/bin/env bash
while read -r host port; do
  if curl -s --max-time 8 --proxy \"socks5h://${host}:${port}\" https://api.ipify.org >/dev/null; then
    echo \"ok   ${host}:${port}\"
  else
    echo \"dead ${host}:${port}\"
  fi
done < upstreams.txt

按计划运行它,过滤掉失效的条目,然后重新加载。这个单一的习惯可以防止大多数“为什么我的爬虫突然被屏蔽了”的早晨。

最后,保持在界限内:只使用你被授权使用的代理,并尊重每个目标网站的条款、robots 指令和速率限制。网关使发送流量更容易——它不会使不受欢迎的流量变得可接受。

这如何与你已经运行的工具配合

如果某个库已经轮换得很好,就保留它。网关补充而不是取代 Python 的 requests、Scrapy 或 Selenium 中的按请求中间件;它覆盖了完全没有轮换方案的工具,并为 rank-tracker 风格的工作负载提供每个国家/地区的固定出口。如果你正在专门权衡客户端与网关轮换用于爬取,我们的“用于网页爬取的轮换代理”指南涵盖了中间件模式,而 Selenium 轮换代理演练涵盖了使网关首先具有吸引力的浏览器启动约束。

简短版本

  • 轮换代理网关是代理的本地负载均衡器:一个端点,多个上游
  • 同时运行 HTTP 监听器和 SOCKS5 监听器;为粘性工作运行一个固定到一个节点的第二个端口
  • 当位置重要时,将 DNS 解析保留在出口节点
  • 在对设置信任之前,用针对 api.ipify.org 和 cdn-cgi/trace 的循环进行验证
  • 绑定到 localhost,如果可以的话进行认证,并安排健康检查,以便失效的出口离开池