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 може підмінити цей набір.
  • Проблема із сертифікатом самого сайту. Сертифікат прострочений або виданий на інший домен. Тоді помилка буде і без проксі.

Як виправити

  1. Для порту 823 і портів 10000–20000 у режимі HTTP пишіть схему http://: 'https': 'http://ЛОГІН:ПАРОЛЬ@gw.prokso.com:823'. Ключ 'https' у словнику означає схему сайту, а не проксі.
  2. Для SOCKS5 використовуйте socks5h://ЛОГІН:ПАРОЛЬ@gw.prokso.com:824 і встановіть залежності SOCKS. Приклади для обох протоколів є в інструкції Python requests, а всі порти й формати рядка — у довіднику про шлюз.
  3. Оновіть пакети командою pip install -U requests certifi і перевірте, чи не задано REQUESTS_CA_BUNDLE і CURL_CA_BUNDLE: env | grep CA_BUNDLE.
  4. Якщо працюєте в корпоративній мережі чи з антивірусом, що сканує HTTPS, передайте шлях до їхнього кореневого сертифіката: verify='/шлях/до/ca.pem'.
  5. Не ставте 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="/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 ГБ

Реєстрація за хвилину, доступи одразу після оплати.

Створити акаунт