Сообщение об ошибке
[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol
Также выводится как
- ssl.SSLEOFError: EOF occurred in violation of protocol
С OpenSSL 3 Python показывает код причины «[SSL: UNEXPECTED_EOF_WHILE_READING]»; с OpenSSL 1.1.1 текст просто «EOF occurred in violation of protocol». Далее следует место в исходном коде, например «(_ssl.c:1082)».
Python ssl module (OpenSSL) — ssl.SSLEOFError, SSL_R_UNEXPECTED_EOF_WHILE_READING
Что это означает
Другая сторона закрыла TCP-соединение, пока Python ещё выполнял TLS-рукопожатие (или посреди чтения данных), не отправив ни оповещения TLS, ни close_notify. OpenSSL считает такой молчаливый обрыв нарушением протокола. Python не может знать, почему другая сторона отключилась: причина на сервере, в прокси или в межсетевом экране между ними.
Почему это происходит
Сервер обрывает рукопожатия, которые ему не нравятся
частоНекоторые серверы и балансировщики нагрузки вместо отправки оповещения закрывают соединение, если в ClientHello нет SNI, нет приемлемой версии или шифра либо имя не настроено.
Прокси, межсетевой экран или VPN обрывает соединение
частоНеверные настройки прокси (HTTPS_PROXY указывает на TLS-порт прокси, для внутренних хостов не задан NO_PROXY), глубокая инспекция пакетов, которая блокирует адрес назначения, или VPN-клиенты часто молча обрывают TCP-соединение.
Ограничение частоты запросов или защита от ботов
иногдаПерегруженные API и CDN или антибот-системы, которым не нравится отпечаток TLS от Python, могут сбрасывать соединения вместо того, чтобы вернуть ошибку HTTP.
Сервер закрыл соединение посреди ответа
иногдаЕсли ошибка возникает при чтении ответа, значит, сервер или прокси оборвал соединение без close_notify, например после тайм-аута или падения рабочего процесса.
Как исправить
- 1.
Воспроизведите рукопожатие с помощью openssl s_client
Если s_client тоже отключают, меняйте SNI и версию TLS, чтобы понять, что не устраивает сервер; если s_client работает, сравните его настройки с настройками вашего клиента на Python (прокси, SNI, версии).
bash # Does a plain OpenSSL handshake work from the same machine? openssl s_client -connect api.example.com:443 -servername api.example.com -brief </dev/null # Without SNI, and pinned to TLS 1.2, to see what the server objects to openssl s_client -connect api.example.com:443 -noservername -brief </dev/null openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2 -brief </dev/null - 2.
Проверьте переменные окружения для прокси
requests, urllib и pip учитывают HTTPS_PROXY и NO_PROXY. Исправьте схему в URL прокси и исключите внутренние хосты, к которым нужно обращаться напрямую.
bash env | grep -i -E '^(https?|no|all)_proxy=' # Proxy URLs should normally be http:// (CONNECT tunnel), and internal hosts listed in NO_PROXY export HTTPS_PROXY=http://proxy.example.net:3128 export NO_PROXY=localhost,127.0.0.1,.internal.example.com - 3.
Повторяйте попытки, если причина временная
При ограничении частоты запросов и нестабильной сети повторные попытки с нарастающей задержкой превращают редкие сбросы соединения в успешные, хотя и более медленные запросы; сервер, который всегда отклоняет рукопожатие, они не исправят.
python import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session = requests.Session() session.mount("https://", HTTPAdapter(max_retries=Retry(total=3, backoff_factor=1))) session.get("https://api.example.com/")
Связанные ошибки
[SSL: WRONG_VERSION_NUMBER] wrong version numberPython ssl module (OpenSSL)curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while…curl (OpenSSL 3 backend)error:0A000126:SSL routines::unexpected eof while readingOpenSSL 3Client network socket disconnected before secure TLS connection was establishedNode.js tls / https / fetch