SSLError через прокси в requests и urllib3
Защищённое соединение не установилось: либо программа попыталась говорить TLS с прокси, который ждёт обычный HTTP, либо сертификат сайта не прошёл проверку.
Обновлено · Редакция Prokso
- Ошибка wrong version number через прокси почти всегда означает схему https:// в строке HTTP-прокси
- CERTIFICATE_VERIFY_FAILED касается сертификата сайта: прокси в туннеле CONNECT шифрование не меняет
- Пишите http:// для порта 823, обновите certifi и не отключайте проверку через verify=False
Что означает ошибка
Когда requests открывает https-сайт через HTTP-прокси, он сначала просит прокси открыть туннель методом CONNECT. Дальше прокси только передаёт байты, а шифрованное соединение устанавливается между вашим кодом и сайтом. Поэтому сертификат, который проверяет requests, прислал сайт, а не прокси.
Самая частая ошибка здесь — строка прокси со схемой https://. Тогда urllib3 пытается установить TLS с самим прокси, а порт 823 ждёт обычный HTTP. В ответ приходит не TLS, и OpenSSL пишет [SSL: WRONG_VERSION_NUMBER] wrong version number. В текущей urllib3 2.x это обёрнуто в ProxyError с подсказкой Your proxy appears to only use HTTP and not HTTPS, try changing your proxy URL to be HTTP.
CERTIFICATE_VERIFY_FAILED — другая ситуация: TLS с сайтом начался, но цепочка сертификатов не прошла проверку. Через туннель CONNECT причины те же, что и без прокси: устаревший набор корневых сертификатов, подмена сертификата антивирусом или корпоративной сетью, переменные REQUESTS_CA_BUNDLE или CURL_CA_BUNDLE, указывающие на другой файл.
Причины
- Схема https:// для HTTP-прокси. Строка https://ЛОГИН:ПАРОЛЬ@gw.prokso.com:823 заставляет библиотеку шифровать соединение с прокси, и появляется wrong version number.
- Схема http:// на порту SOCKS5. Порт 824 работает только по протоколу SOCKS5. HTTP-запрос на него не получит HTTP-ответа, и текст ошибки будет непонятным.
- Перехват HTTPS. Антивирус или корпоративный шлюз подставляет свой сертификат, и requests сообщает CERTIFICATE_VERIFY_FAILED, часто с текстом self-signed certificate in certificate chain.
- Устаревший certifi или другой CA-файл. Requests берёт корневые сертификаты из пакета certifi, а переменная REQUESTS_CA_BUNDLE может подменить этот набор.
- Проблема с сертификатом самого сайта. Сертификат просрочен или выдан на другой домен. Тогда ошибка будет и без прокси.
Как исправить
- Для порта 823 и портов 10000–20000 в режиме HTTP пишите схему http://:
'https': 'http://ЛОГИН:ПАРОЛЬ@gw.prokso.com:823'. Ключ 'https' в словаре означает схему сайта, а не прокси. - Для SOCKS5 используйте
socks5h://ЛОГИН:ПАРОЛЬ@gw.prokso.com:824и установите зависимости SOCKS. Примеры для обоих протоколов есть в инструкции Python requests, а все порты и форматы строки — в справочнике о шлюзе. - Обновите пакеты командой
pip install -U requests certifiи проверьте, не заданы ли REQUESTS_CA_BUNDLE и CURL_CA_BUNDLE:env | grep CA_BUNDLE. - Если работаете в корпоративной сети или с антивирусом, который сканирует HTTPS, передайте путь к их корневому сертификату:
verify='/путь/к/ca.pem'. - Не ставьте
verify=False. По документации requests этот параметр касается только сертификата сайта: wrong version number от прокси он не уберёт, а CERTIFICATE_VERIFY_FAILED только спрячет, оставив соединение беззащитным перед подменой.
Как проверить, что всё заработало
Запустите requests.get('https://prokso.com/ip', proxies=proxies, timeout=30) с включённой проверкой сертификатов. Если получили JSON с IP прокси, туннель и TLS работают. Для сравнения откройте страницу Мой IP в браузере через тот же прокси: если там ошибки нет, а в коде есть, дело в настройках Python.
Диагностика за 2 минуты
Сначала вставьте строку в проверку прокси. Если там прокси работает, причина в программе или её настройках. Если нет — проверьте строку из терминала:
curl -v -x "http://ЛОГИН:ПАРОЛЬ@gw.prokso.com:823" https://api.ipify.org
- Строка
< HTTP/1.1 407сразу послеCONNECT— отвечает прокси. Название после кода, напримерNO_USER, подсказывает причину. - Прокси ответил на
CONNECTкодом 200, а дальше пришёл другой код — прокси работает, этот ответ дал сайт. - Никакого ответа, только тайм-аут — соединение не дошло до прокси: проверьте хост, порт и сеть.
Инструкции, где встречается эта ошибка
Вопросы и ответы
Может ли прокси Prokso подменить сертификат сайта?
Нет. В туннеле CONNECT шифрование устанавливается между вашей программой и сайтом, а прокси передаёт уже зашифрованные данные. Подробнее — на странице <a href="/ru/errors/ssl-certificate-errors">ошибки SSL и сертификатов</a>.
Сайт на https://, значит, и прокси должен быть https://?
Нет. Схема адреса сайта и схема строки прокси — разные вещи. Сайт может быть на https://, а соединение с прокси на порту 823 — обычным http://, внутри которого идёт шифрованный туннель.
Почему ошибка только в Python, а браузер открывает сайт?
У браузера своё хранилище сертификатов, а requests пользуется пакетом certifi или файлом из переменной REQUESTS_CA_BUNDLE. Обновите certifi и проверьте переменные окружения.
Другие ошибки прокси
Резидентские $1.59, мобильные $2.50, серверные $0.65 за 1 ГБ
Регистрация за минуту, доступы сразу после оплаты.