СправочникПрактика › Формат прокси листа

Формат прокси листа: IP:PORT и IP:PORT:LOGIN:PASS, как загрузить список в программу

Разбор формата прокси листа и загрузки адресов в разные программы

Прокси-лист это текстовый файл, где одна строка описывает один узел пула. Разметки внутри нет, поля разделяются двоеточием, строки отделяются переводом строки. Такой файл читает и человек, и программа, никакой подготовки перед загрузкой он не требует. В пуле iprazon список отдаётся в двух видах, IP:PORT и IP:PORT:LOGIN:PASS, забрать его можно ссылкой или файлом, обновляется выдача в режиме реального времени.

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

Как читается строка и что означает каждое поле

Короткая строка выглядит так: 203.0.113.24:8080. Слева адрес узла, справа номер порта, между ними двоеточие. Полная строка добавляет ещё два поля: 203.0.113.24:8080:u84512:k39dhzp. Третьим идёт имя доступа, четвёртым пароль. Порядок полей закреплён и никогда не меняется. Программа режет строку по двоеточию и раскладывает куски по позициям, поэтому смысл каждого куска задаётся его номером, никаких подписей внутри строки нет.

Четыре поля строки подключения к прокси и назначение каждого поля

Первое поле почти всегда содержит четыре октета IPv4. Иногда в первом поле стоит доменное имя вида gate.example.net, и тогда программа сама превращает его в адрес перед подключением. Второе поле важнее, чем кажется на первый взгляд: у одного и того же узла порт под HTTP и порт под SOCKS5 разные. Взять адрес из HTTP-выдачи и вписать его в поле SOCKS5-клиента получится, работать это не будет: клиент отправит на порт приветствие своего протокола, сервер его не поймёт, соединение оборвётся без внятного текста в логе.

Третье и четвёртое поля появляются только в расширенном формате. Имя доступа и пароль в выдаче одинаковы по всей длине списка, они относятся к пакету целиком. Единственное, за чем я слежу отдельно: двоеточие внутри пароля. Если оно там окажется, разбор строки по позициям поедет, четвёртое поле обрежется на середине, и софт получит неверный пароль при полностью верном адресе. Проверить это стоит один раз, сразу после первой выдачи.

ПолеЧто содержитПримерЧто ломается при ошибке в нём
АдресУзел пула, четыре октета IPv4203.0.113.24Соединение не устанавливается, тайм-аут
ПортНомер порта нужного протокола8080 для HTTP, 1080 для SOCKS5Обрыв на приветствии, лог молчит
ЛогинИмя доступа из кабинетаu84512Код 407 у HTTP, отказ на этапе метода у SOCKS5
ПарольПароль доступа к пулуk39dhzpТот же отказ по допуску, адрес при этом рабочий

Порт стоит держать в конфиге отдельным полем. Склейка порта со строкой руками добавляет ровно один шанс промахнуться на каждую правку. Я храню два значения на пакет и подставляю нужное по схеме подключения, потому что перепутанное значение даёт самую скучную из возможных отладок. Когда нужен именно веб-трафик и разбор ответов по кодам, я беру список HTTP-прокси в двух форматах и раскладываю его по потокам заранее, до старта прогона.

Два формата выдачи и когда берут каждый из них

Разница между IP:PORT и IP:PORT:LOGIN:PASS сводится к тому, где хранится допуск. В коротком формате допуск живёт на стороне сервиса: пул уже знает адрес машины, с которой к нему придут, и пускает по этому признаку. В длинном формате допуск едет вместе с каждой строкой, и пулу неважно, откуда именно пришёл запрос.

Короткий формат приятнее в работе с софтом, у которого поля для имени и пароля вынесены отдельно от поля адреса. Таких программ много: старые чекеры, часть менеджеров закачек, самописные скрипты с двумя переменными в конфиге. Длинный формат приятнее там, где строка одна на всё и разбирается автоматически: массовые загрузчики списков, антидетект-браузеры с пакетным импортом, планировщики задач.

Есть третий сценарий, о котором обычно вспоминают поздно. Список из 12 000 строк удобно раздавать между машинами по частям, и короткий формат для этого не годится: каждая машина должна быть привязана отдельно. Длинный формат переносится куда угодно как обычный текст, и я держу его основным именно поэтому.

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

def parse(line):
    p = line.strip().split(":")
    if len(p) == 2:
        return {"host": p[0], "port": int(p[1])}
    if len(p) == 4:
        return {"host": p[0], "port": int(p[1]), "user": p[2], "pwd": p[3]}
    raise ValueError("строка с неверным числом полей: " + line)

Эта функция у меня стоит первой в любом скрипте, который читает список. Она же ловит мусор: строка с двумя двоеточиями означает, что где-то потерялось поле, и такую запись лучше отбросить сразу, до загрузки в пул потоков.

Привязка адреса в кабинете и доступ по логину

Оба режима допуска дают одинаковый результат на выходе, различаются они удобством и тем, что придётся хранить. Привязка адреса настраивается в кабинете: вы вписываете туда адрес своей машины, и пул начинает пускать запросы с него без пароля. В пакет входит две привязки одновременно, менять их можно свободно и сколько угодно раз, поэтому переезд на другой канал занимает минуту.

Сравнение привязки своего адреса и доступа по логину при работе со списком

Я держу привязку на стационарном стенде, где канал не меняется неделями. Строки в конфиге короткие, паролей в файлах нет, при передаче конфига коллеге ничего лишнего не утекает. Одна деталь тут заметна не сразу: при двух привязанных адресах общий лимит потоков делится между ними пополам. Если обе машины работают одновременно и вы рассчитывали на полный лимит, поведение под нагрузкой окажется неожиданным. Я планирую нагрузку сразу от половины, когда привязок две.

Доступ по логину я использую на всём, что живёт в облаке и меняет адрес при перезапуске. Виртуалка получила новый адрес после переезда, конфиг остался прежним, прогон продолжился. Плата за это одна: пароль лежит в конфигурационном файле, значит файл нужно закрывать правами доступа и не таскать его в общий репозиторий. Я держу такие конфиги отдельной директорией и подкладываю их на машину при развёртывании.

Смешивать режимы в пределах одного прогона незачем. Выберите один и держите его по всему парку машин, иначе через месяц вы будете помнить только про половину настроек. Когда важно, чтобы целевой узел видел ровно один выходной адрес без служебных заголовков сверху, я собираю прогон на анонимные приватные адреса из пула и оставляю на них длинный формат строки.

ПризнакПривязка адресаЛогин с паролем
Формат строкиIP:PORTIP:PORT:LOGIN:PASS
Что настраиваетсяАдрес машины в кабинетеНичего, допуск в строке
Смена каналаПравка привязки в кабинетеНичего править не нужно
Сколько машинДве привязки в пакетеЛюбое число машин
ПотокиПри двух привязках делятся пополамОбщий лимит пакета
Что хранитьТолько адреса и портыЕщё имя доступа и пароль

Схема в начале строки: http, socks5 и socks5h

Список отдаётся без схемы, схему подставляет программа. В большинстве полей ввода она подставляется автоматически, в коде и в командной строке её пишут руками. Полная запись выглядит так: socks5://u84512:k39dhzp@203.0.113.24:1080. Здесь схема, дальше имя и пароль через двоеточие, дальше собака, дальше адрес с портом. Тот же узел по HTTP пишется как http://u84512:k39dhzp@203.0.113.24:8080.

Схема описывает канал до пула, целевой сайт тут ни при чём. Строка с http:// спокойно обслуживает обращение к адресу на https: клиент шлёт пулу метод CONNECT, тот поднимает канал, дальше шифрование идёт между вашей программой и сайтом. Писать https:// в поле только потому, что целевая ссылка начинается с https, смысла нет, и такая правка даёт ошибку рукопожатия.

Отдельная история с буквой h в схеме socks5h. Она говорит клиенту передать доменное имя на сторону пула строкой и дать серверу превратить имя в адрес самому. Без неё имя превращается в адрес на вашей машине, и запрос в DNS уходит мимо пула. Разница проявляется в том, какой резолвер отвечает на вопрос, скорость тут одинаковая. Я ставлю socks5h везде, где программа эту схему понимает.

curl -x socks5h://u84512:k39dhzp@203.0.113.24:1080 https://api.ipify.org
curl -x http://u84512:k39dhzp@203.0.113.24:8080 https://api.ipify.org

Два вызова подряд, две проверки. Оба должны вернуть адрес узла пула, и оба должны вернуть разные адреса при повторе: ротация внутри пула идёт автоматически. Пакет включает SOCKS4 и SOCKS5 на выбор, я останавливаюсь на пятой версии всегда, у неё есть допуск по логину и работа с доменными именами. Когда прогон идёт к сайтам по защищённой схеме через тот же туннель CONNECT, я подключаю точку входа для запросов по HTTPS и держу под неё отдельное поле порта в конфиге.

Ссылка на список и файл: как забирать выдачу

В кабинете доступны два способа получить список: ссылка и скачивание файлом. Отличие простое. Файл это снимок на момент нажатия кнопки. Ссылка отдаёт текущее содержимое пула каждый раз, когда по ней пришли.

Файл я беру, когда список нужно показать глазами, разложить по машинам вручную или отдать программе, которая умеет только импорт с диска. Ссылку беру во всём, что работает по расписанию. Список обновляется в реальном времени, значит скрипт может забрать свежий вариант перед каждым запуском и не думать о том, насколько устарел файл на диске.

curl -s "https://cabinet.example/list/u84512/full" -o /opt/pool/list.txt
wc -l /opt/pool/list.txt

Две строки в задании планировщика, и парк машин всегда работает от актуальной выдачи. Вторая строка тут стоит по делу: если ссылка вернула пустой ответ или страницу с ошибкой, число строк это сразу покажет, и прогон не стартует на пустом списке. Я добавляю простую проверку: файл короче ста строк считается негодным, и скрипт оставляет предыдущий вариант.

Ещё один момент про ссылку. Она отдаёт текст, значит её содержимое можно направить прямо в программу, минуя диск. У части парсеров есть поле для адреса списка, куда ссылка вставляется целиком, и софт сам ходит за обновлением по своему расписанию. Такой вариант я предпочитаю всему остальному: одна настройка закрывает сразу и задание в планировщике, и файл на диске. Трафик за такие обращения не считается никак, безлимит по объёму в любом пакете снимает вопрос о частоте обновления полностью.

Форматы под разные программы: расширение и антидетект-браузер

Софт делится на четыре группы по тому, как он принимает адрес. Понимание группы экономит время: становится ясно, какой из двух форматов брать и в каком виде подавать выдачу.

Тип программыКакой формат принимаетКак подаётсяНа что смотреть
Расширение браузераПоля по отдельностиАдрес, порт, имя, пароль рукамиСхема выбирается списком, не текстом
Антидетект-браузерСтрока целикомВставка в поле или импорт файломРазделитель полей задаётся настройкой
Парсер со своим менеджеромФайл или ссылкаЗагрузка списка целикомПорядок полей выбирается шаблоном
Код и командная строкаСтрока со схемойСборка из полей внутри программыСпецсимволы в пароле кодируются

Две первые группы разбираю прямо здесь, две оставшиеся в следующем разделе.

Расширение браузера принимает поля по одному. Тут длинный формат приходится разбирать глазами: адрес в первое поле, порт во второе, имя в третье, пароль в четвёртое. Самая частая ошибка выглядит как вставка 203.0.113.24:8080 целиком в поле адреса. Расширение примет строку молча, порт возьмёт из своего значения по умолчанию, и браузер пойдёт мимо пула. Признак у этого один: страница открывается, а сервис проверки показывает адрес вашего канала. Поле адреса принимает только адрес.

Схема в расширении выбирается отдельным переключателем со значениями HTTP и SOCKS5. Переключатель нужно менять вместе с портом. Я видел десяток случаев, когда человек менял порт с HTTP на SOCKS5 и забывал переключатель, после чего решал, что узел нерабочий.

Антидетект-браузер удобнее: он принимает строку целиком и разбирает её сам. В настройках профиля обычно есть выбор порядка полей, потому что часть поставщиков отдаёт список в перевёрнутом виде, с именем и паролем впереди адреса. Порядок нужно выставить один раз под свою выдачу и дальше не трогать. Массовый импорт из файла раскладывает строки по профилям по очереди, одна строка на профиль, и это самый быстрый путь развернуть несколько десятков профилей за раз. Под такой сценарий я готовлю прокси под антидетект-браузер заранее и слежу, чтобы число строк в файле совпадало с числом профилей.

Проверка после импорта занимает минуту и делается встроенным чекером профиля. Он показывает адрес и отклик по каждому профилю списком. Если у части профилей поле пустое, значит файл содержал меньше строк, чем нужно, и хвост профилей остался без адресов.

Парсер со своим менеджером списка и подстановка из кода

У серьёзных парсеров есть свой менеджер прокси, и он ждёт список файлом или ссылкой. Формат там задаётся шаблоном: программа спрашивает, что стоит на первой позиции, что на второй, какой символ служит разделителем. Шаблон выставляется один раз под выдачу поставщика. После этого файл грузится целиком, и менеджер сам раздаёт строки потокам, помечая нерабочие.

Важная настройка в таких менеджерах называется по-разному, смысл у неё один: сколько потоков разрешено пускать через одну строку списка. Я ставлю единицу, когда прогон идёт по площадке с жёстким счётом обращений с адреса, и три, когда счёт мягкий. Общий предел по пакету при этом остаётся своим, до 1000 потоков на обычных пакетах и до 3000 на корпоративном, и превысить его настройкой парсера нельзя.

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

from urllib.parse import quote

def to_url(p, scheme="socks5h"):
    if "user" in p:
        u, w = quote(p["user"], safe=""), quote(p["pwd"], safe="")
        return f"{scheme}://{u}:{w}@{p['host']}:{p['port']}"
    return f"{scheme}://{p['host']}:{p['port']}"

Функция короткая и закрывает оба формата сразу. Строка без имени и пароля соберётся в вид socks5h://203.0.113.24:1080, и такой конфиг корректен при работе через привязанный адрес.

Пять причин сорванной загрузки списка

Собрал статистику по своим разборам: 60 обращений подряд, где список не завёлся с первого раза. Ни один из случаев не относился к самому пулу, все пять причин сидели в тексте файла.

Пять причин, по которым загрузка списка прокси срывается без сообщения

Пробелы по краям строк дали 19 случаев из 60. Появляются они при копировании из мессенджера, из таблицы, из письма. Программа берёт строку целиком вместе с пробелом, пытается превратить 203.0.113.24 в адрес и получает отказ. Лечится обрезкой краёв у каждой строки, в коде это strip, в редакторе замена по регулярному выражению.

Порт в поле адреса дал 14 случаев. Разобрал выше на примере расширения, добавлю только, что та же ошибка встречается в конфигах systemd и в переменных окружения, где адрес и порт положено разносить.

Перенос строк в стиле CRLF дал 12 случаев. Файл, сохранённый в Windows, несёт в конце каждой строки два символа, и на Linux второй из них остаётся хвостом в последнем поле. Пароль превращается в k39dhzp\r, допуск отклоняется, адрес при этом верный. Диагностируется мгновенно: если в логе видно отказ по паролю на всех строках сразу, смотрите переносы. Команда file list.txt покажет тип переносов, dos2unix их поправит.

Кодировка с меткой BOM дала 9 случаев. Метка невидима в редакторе и сидит в самом начале файла, поэтому портится ровно одна строка, первая. Программа отбрасывает её как битую и молча работает с остальными, а вы считаете, что загрузился весь список. Сохраняйте файл в UTF-8 без метки.

Пустая строка в конце файла дала 6 случаев. Некоторые менеджеры считают её записью и добавляют в пул пустой узел, после чего каждый N-й запрос уходит в никуда. Проверка на пустоту в парсере строк закрывает этот случай навсегда.

Как проверить строку до загрузки в софт

Порядок у меня одинаковый для любой программы, и занимает он меньше минуты. Сначала одна строка проверяется вручную через curl, и только потом список едет в софт целиком. Смысл в том, чтобы отделить проблему текста от проблемы настроек программы.

head -n1 list.txt | tr -d '\r' | awk -F: '{print "socks5h://"$3":"$4"@"$1":"$2}'

Команда берёт первую строку списка, срезает хвост переноса и собирает готовую строку подключения. Её остаётся подставить в curl и посмотреть ответ сервиса эха. Пришёл адрес узла пула значит формат разобран верно, и дальше можно грузить весь файл.

Массовую проверку я делаю тем же скриптом по всему списку, с ограничением по времени ответа. Пять секунд на попытку хватает: узел, который не ответил за это время, я в прогон не беру.

while IFS=: read -r ip port user pwd; do
  out=$(curl -s -m 5 -x "socks5h://$user:$pwd@$ip:$port" https://api.ipify.org)
  echo "$ip:$port $out"
done < <(tr -d '\r' < list.txt)

Вывод пишется в файл и просматривается глазами за полминуты. Строки с пустым вторым полем это отказ, их я откладываю и перепроверяю через несколько минут: ротация внутри пула идёт постоянно, и через проход состав отвечающих узлов меняется. Отдельно советую держать в кабинете тестовый прогон перед покупкой, бесплатный тест до 2 часов как раз позволяет проверить формат под свой софт до оплаты.

Как обновлять список без остановки работы

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

Первый шаг: свежая выдача скачивается во временный файл. Второй шаг: временный файл проверяется на длину и на разбор первой строки. Третий шаг: файл переименовывается поверх рабочего, и это действие атомарно в пределах одной файловой системы. Программа, которая читает список по расписанию, подхватит новый вариант при следующем чтении и никогда не увидит наполовину записанный файл.

curl -s "$LIST_URL" -o /opt/pool/.new
[ $(wc -l < /opt/pool/.new) -ge 100 ] && mv /opt/pool/.new /opt/pool/list.txt

Для софта со своим менеджером порядок другой: там обновление вызывается кнопкой или по таймеру самой программы, и трогать файл на диске незачем. Я выставляю таймер на час и не вмешиваюсь. Для кода живее всего работает вариант с очередью: скрипт перечитывает список раз в несколько минут, добавляет новые строки в конец очереди и убирает те, что перестали отвечать. Прогон при этом идёт без пауз.

Когда список нужен на нескольких машинах, я забираю его один раз на управляющем узле и раздаю оттуда. Так все машины работают от одинакового набора строк, и разбор проблем сильно упрощается. Для веб-прогонов на этих машинах я держу приватные HTTP-адреса под загрузку списком, а порт SOCKS5 подставляю из того же файла второму классу задач.

Соседние материалы вики по теме: прокси для досок объявлений разбирают работу с профилями площадок, сбор отзывов и репутации бренда показывает прогоны по карточкам, лимит потоков и расчёт нагрузки объясняет, как разложить пакет по задачам, а порт прокси-сервера подробно разбирает второе поле строки и его значения по протоколам.