Skip to content
Статья / 3 мин. чтения

Шлюз ротации прокси: одна локальная точка SOCKS5 или HTTP для всего вашего пула прокси

Направьте все инструменты на одну локальную точку SOCKS5 или HTTP и позвольте небольшому шлюзовому сервису выбирать вышестоящий прокси для каждого подключения — с конфигурацией, закреплёнными сессиями, проверками работоспособности, DNS и проверкой утечек.

Шлюз ротации прокси: одна локальная точка SOCKS5 или HTTP для всего вашего пула прокси

Ротация прокси внутри вашего кода работает нормально, пока не появится второй инструмент. Теперь у вас есть скрапер с middleware, браузер, которым вы управляете вручную, CLI-чекер позиций с одним полем для прокси и cron-задача, написанная кем-то другим, — каждый ротирует по-своему или не ротирует вовсе.

Шлюз ротации прокси устраняет это дублирование. Вы запускаете один небольшой сервис локально (или на VPS), направляете всё на 127.0.0.1:8080, и шлюз выбирает вышестоящий прокси для каждого подключения. В этом руководстве рассказывается, что это за сервис, когда стоит идти на лишний хоп, как собрать его с конфигом, который действительно можно прочитать, и как убедиться в ротации, разрешении DNS и отсутствии утечек, прежде чем доверять ему рабочую нагрузку.

Что такое шлюз ротации прокси на самом деле

Это балансировщик нагрузки для прокси. Путь запроса выглядит так:

  1. Клиент — браузер, curl, Scrapy, Selenium, десктопное приложение
  2. Шлюз — локальный слушатель HTTP или SOCKS5 на вашей машине
  3. Выбор — шлюз выбирает один вышестоящий прокси из вашего пула
  4. Выходной узел — вышестоящий прокси выполняет исходящий запрос
  5. Целевой сайт — видит IP выходного узла, а не ваш

Шлюз не делает прокси быстрее, приватнее или надёжнее. Он централизует выбор, учётные данные и работоспособность — это другая задача, нежели та, которую решает клиентская ротация.

Когда шлюз лучше ротации внутри вашего кода

Используйте шлюз, когда:

  • Нескольким инструментам нужны прокси, и лишь некоторые из них поддерживают ротацию из коробки
  • Вы хотите одно место для обновления учётных данных, когда провайдер меняет ваш пароль или порт
  • Вам нужны закреплённые сессии для сценариев с авторизацией и ротация на каждый запрос для скрапинга — рядом друг с другом
  • Вы хотите единую точку для проверок работоспособности, обнаружения блокировок и оценки вышестоящих прокси
  • Вы хотите одинаковое поведение DNS во всех клиентах вместо особенностей каждой библиотеки
  • Возможно, позже вы перенесёте нагрузку с ноутбука на VPS или CI-раннер

Откажитесь от шлюза, когда:

  • У вас ровно один клиент, и у него уже есть хороший middleware (например, rotating-proxy middleware в Scrapy)
  • Ротация зависит от бизнес-правил для каждого запроса — гео-таргет, аккаунт, ценовой уровень
  • Вам нужна статистика задержек и сбоев по каждому запросу для конкретного использованного вышестоящего прокси, а шлюз её не предоставляет

Лишний хоп добавляет немного задержки. Для большинства задач автоматизации это погрешность по сравнению с временем отклика самого выходного узла.

Сначала выберите протокол слушателя

Слушатель Поддержка клиентами Аутентификация Поведение DNS На что обратить внимание
HTTP (CONNECT) Почти универсальна, включая приложения только с полем «HTTP proxy» Basic-аутентификация широко поддерживается Зависит от коннектора вышестоящего прокси Обычные 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 перебирает узлы по порядку, а некоторые версии добавляют случайный выбор или выбор на основе хеша. Сверьтесь с документацией по селектору для вашего конкретного релиза, а не предполагайте, что название стратегии существует; если нужной функции нет, трюк с отдельным портом на каждую стратегию из следующего раздела обычно всё равно решает задачу.

Для всего долгоиграющего 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 и утечек

Никогда не предполагайте, что шлюз делает то, что написано в конфиге. Две минуты проверки экономят неделю работы с запутанными данными.

Начните с цикла в shell по HTTP-слушателю:

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

Оба должны выходить в интернет; разница в том, передаётся ли на выходной узел имя хоста или уже разрешённый адрес. Для геозависимых задач нужен именно удалённый вариант разрешения, и он должен поддерживаться от начала до конца — и шлюзом, и вышестоящим прокси.

Краткий чек-лист по утечкам:

  • Ни один ответ никогда не должен показывать ваш реальный 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 и ограничения по скорости. Шлюз упрощает отправку трафика — он не делает нежелательный трафик приемлемым.

Как это сочетается с инструментами, которые вы уже используете

Если библиотека уже хорошо ротирует, оставьте её. Шлюз дополняет, а не заменяет middleware для каждого запроса в Python requests, Scrapy или Selenium; он покрывает инструменты, у которых вообще нет истории с ротацией, и даёт нагрузкам в стиле трекеров позиций закреплённый выход для каждой страны. Если вы взвешиваете клиентскую ротацию против шлюзовой конкретно для скрапинга, наше руководство по ротируемым прокси для веб-скрапинга охватывает шаблоны middleware, а разбор ротируемых прокси в Selenium описывает ограничения запуска браузера, из-за которых шлюз и становится привлекательным.

Коротко

  • Шлюз ротации прокси — это локальный балансировщик нагрузки для прокси: одна точка, много вышестоящих прокси
  • Запускайте и HTTP-, и SOCKS5-слушатель; запустите второй порт, закреплённый за одним узлом, для закреплённой работы
  • Оставляйте разрешение DNS на выходном узле, когда важна геолокация
  • Проверяйте циклом по api.ipify.org и cdn-cgi/trace, прежде чем доверять конфигурации
  • Привязывайтесь к localhost, включайте аутентификацию, если можете, и назначайте проверку работоспособности по расписанию, чтобы мёртвые выходы покидали пул