С чего начать
Все способы выбора прокси в curl — от одного флага -x до переменных окружения — с деталями аутентификации, SOCKS5 и туннеля, от которых зависит, выполнится ли запрос.
Прокси для одного запроса через -x
Опция -x, в длинной форме --proxy, направляет один запрос curl через прокси. Укажите схему, хост и порт прокси. Если схема опущена, curl подставляет http://, а если опущен порт — 1080, поэтому указывайте и то и другое явно.
Схема описывает соединение с прокси, а не с целевым сервером. Для целевого адреса https:// через обычный HTTP-прокси по-прежнему используется -x http://host:port; curl открывает через него туннель CONNECT. Пишите -x https://host:port только тогда, когда провайдер терминирует TLS на самом прокси. curl также принимает здесь socks4://, socks4a://, socks5:// и socks5h://.
Команда ниже сохраняет две привычки из остальной части руководства: --disable игнорирует curlrc, который мог бы добавить собственный прокси, а --noproxy '' отменяет любое унаследованное исключение no_proxy, так что запрос действительно уходит через указанный вами шлюз. proxy.example.invalid намеренно не резолвится; подставьте шлюз вашего провайдера.
curl -x · один запрос через прокси
curl --disable --noproxy '' \
-x http://proxy.example.invalid:8080 \
https://example.com/Аутентификация на прокси: -U, --proxy-user и 407
Учётные данные прокси отделены от учётных данных целевого сервера. -U или --proxy-user отправляет их прокси; -u или --user отправляет их целевому серверу. Если их перепутать, вы получите 407 от прокси или 401 от целевого сервера, хотя пароль верный.
Учётные данные можно также встроить в URL прокси в виде http://user:password@host:port. Сначала закодируйте зарезервированные символы через percent-encoding: символ @ в пароле должен превратиться в %40, иначе curl воспримет его как начало хоста. По умолчанию для аутентификации на прокси используется схема Basic; --proxy-digest, --proxy-ntlm и --proxy-anyauth выбирают другие схемы, если провайдер их документирует.
В обоих вариантах пароль попадает в список аргументов процесса и в историю оболочки. Вместо этого читайте его из переменной или используйте форму --variable и --expand-proxy-user из curl 8.3, показанную в диагностическом скрипте ниже: она импортирует секрет, не раскрывая его как аргумент.
- connect=407 или сообщение Received HTTP code 407 from proxy after CONNECT означает, что прокси отклонил учётные данные или не получил их вовсе. Проверьте значение -U, кодирование и формат имени пользователя у провайдера.
- 401 от целевого сервера при успешном туннеле — проблема целевого сервера; этап прокси уже работает.
- Многие провайдеры кодируют параметры страны, сессии или протокола в имени пользователя. Точно следуйте документированному формату провайдера; curl передаёт строку без изменений.
curl --proxy-user · учётные данные из окружения
: "${PROXY_USERNAME:?}" "${PROXY_PASSWORD:?}"
curl --disable --noproxy '' \
-x http://proxy.example.invalid:8080 \
--proxy-user "$PROXY_USERNAME:$PROXY_PASSWORD" \
https://example.com/Переменные окружения: http_proxy, https_proxy, no_proxy и .curlrc
Без -x curl ищет прокси в окружении. Переменную http_proxy он читает только в нижнем регистре, потому что имя в верхнем регистре может быть установлено заголовками CGI-запроса; https_proxy или HTTPS_PROXY, all_proxy или ALL_PROXY, а также no_proxy или NO_PROXY он принимает в обоих вариантах. Переменная выбирается по схеме целевого адреса: для https:// используется https_proxy, поэтому если экспортировать только http_proxy, HTTPS-трафик пойдёт напрямую.
no_proxy — список имён хостов или суффиксов доменов через запятую, которые обходят прокси; одиночная * полностью отключает проксирование. -x в командной строке всегда имеет приоритет над окружением, а --noproxy в командной строке всегда имеет приоритет над no_proxy.
Файл ~/.curlrc может задавать proxy = "http://host:port" для каждого вызова — это удобно на рабочей станции и неожиданно внутри контейнера или CI-задания. Запускайте curl с --disable или его короткой формой -q первым аргументом, когда скрипт должен его игнорировать.
http_proxy и https_proxy · сессия оболочки
export http_proxy='http://proxy.example.invalid:8080'
export https_proxy='http://proxy.example.invalid:8080'
export no_proxy='localhost,127.0.0.1,.internal.example'
curl https://example.com/ # uses https_proxy
curl --noproxy '*' https://example.com/ # bypasses the proxy onceSOCKS5 в curl: socks5 против socks5h
curl работает с SOCKS через ту же опцию -x. socks5:// резолвит имя целевого хоста на вашей машине и отправляет прокси IP-адрес. socks5h:// отправляет имя хоста и позволяет прокси резолвить его самому — это то, что нужно, когда целевой адрес должен резолвиться из сети прокси или когда локальный DNS вообще не должен видеть целевой адрес. Длинные опции --socks5 и --socks5-hostname эквивалентны.
Аутентификация по имени пользователя и паролю для SOCKS5 использует ту же опцию --proxy-user. У SOCKS нет статуса CONNECT, поэтому отклонённое рукопожатие проявляется как код выхода curl 97 с краткой причиной, а не как 407.
curl socks5h · DNS на стороне прокси
curl --disable --noproxy '' \
-x socks5h://proxy.example.invalid:1080 \
--proxy-user "$PROXY_USERNAME:$PROXY_PASSWORD" \
https://example.com/Целевые адреса HTTPS: туннель CONNECT и -v
Для целевого адреса https:// через HTTP-прокси curl сначала отправляет прокси CONNECT example.com:443. Только после того, как прокси ответит 200, curl начинает TLS с целевым сервером внутри туннеля, так что прокси никогда не видит расшифрованный запрос. Запустите с -v, чтобы увидеть оба шага; ответ на CONNECT приходит раньше любых заголовков целевого сервера. -p или --proxytunnel принудительно использует такой же туннель для обычного целевого адреса http://.
Для обычного целевого адреса http:// туннеля нет. curl отправляет прокси полный URL, прокси загружает его, и заголовки ответа, которые вы видите, могут прийти от любой из сторон. Когда код статуса нужно отнести к определённому слою, предпочитайте туннелируемый вариант и читайте статус CONNECT отдельно через переменную %{http_connect} в --write-out.
С прокси https:// curl проверяет сертификат прокси так же, как и сертификат целевого сервера. --proxy-cacert задаёт собственный набор доверенных сертификатов для прокси; оставляйте обе проверки включёнными вместо того, чтобы прибегать к --proxy-insecure или -k.
Отправьте один ограниченный запрос как базовую проверку
Сохраните это как proxy-check.sh и запустите командой sh proxy-check.sh. Требуется curl 8.3 или новее и аутентификация на прокси по HTTP Basic. Пусть ваш менеджер секретов заполнит PROXY_USERNAME и PROXY_PASSWORD, а в PROXY_URL укажите шлюз вашего провайдера со схемой и портом; https://proxy.example.invalid:8443 — иллюстративное значение, которое намеренно не подключается.
curl импортирует учётные данные сам, поэтому раскрытый пароль никогда не становится аргументом оболочки. Команда печатает статус целевого сервера, статус CONNECT и затраченное время, а тело ответа отбрасывает. Сохраните эту базовую проверку, прежде чем добавлять браузер, параллелизм или код приложения.
proxy-check.sh · curl 8.3+
: "${PROXY_URL:?Set your provider proxy URL}"
curl --disable --silent --show-error --fail \
--noproxy '' \
--proxy "$PROXY_URL" \
--variable %PROXY_USERNAME \
--variable %PROXY_PASSWORD \
--expand-proxy-user '{{PROXY_USERNAME}}:{{PROXY_PASSWORD}}' \
--connect-timeout 10 --max-time 30 \
--output /dev/null \
--write-out 'http=%{http_code} connect=%{http_connect} seconds=%{time_total}\n' \
'https://example.com/'Читайте коды выхода curl и находите отказавший слой
Успешный ответ доказывает, что этот запрос выполнился; он не устанавливает конкретную страну выхода или оператора. Для этого используйте документированную диагностическую конечную точку вашего провайдера или конечную точку под вашим контролем, которая сообщает наблюдаемый адрес источника.
Сравнивая своё приложение с curl, сохраняйте тот же целевой адрес и те же учётные данные. Если изменить три настройки сразу, успешный повтор будет трудно объяснить. Передавайте в поддержку код выхода, тайминги и очищенный статус, а не подробную трассировку с данными аутентификации.
- Код 5, could not resolve proxy: имя хоста шлюза неверно или локальный DNS его не видит.
- Код 7, failed to connect: хост прокси разрешился, но порт закрыт, фильтруется или недоступен из этой сети.
- Код 28, operation timed out: один раз увеличьте --connect-timeout или --max-time для подтверждения, а повторение считайте проблемой маршрутизации или ёмкости.
- Код 56 с Received HTTP code 407 from proxy after CONNECT: аутентификация на прокси не прошла; исправьте -U, прежде чем трогать заголовки целевого сервера.
- Код 97, proxy handshake error: рукопожатие SOCKS отклонено; проверьте схему socks5 против socks5h и учётные данные.
- Код 35 или 60, ошибка TLS: проверьте имя хоста, цепочку доверия и часы. Оставляйте проверку сертификатов включённой.
Перед выпуском
- Используйте реальный шлюз вашего провайдера со схемой и портом, которые он документирует.
- Передавайте учётные данные приватно; не вставляйте секреты в историю оболочки.
- Зафиксируйте одну ограниченную базовую проверку, прежде чем тестировать параллельный трафик.
- Прежде чем менять настройки, отметьте, произошёл ли сбой на этапе CONNECT или на целевом сервере.
Источники и дополнительное чтение
Технические материалы, использованные при подготовке руководства. Сверяйтесь с документацией вашей версии и с поддерживаемой конфигурацией вашего провайдера.