Перейти к содержимому
ecdsa.com
Python ssl module (OpenSSL)Python: пакет cryptography

Сообщение об ошибке

[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 не может знать, почему другая сторона отключилась: причина на сервере, в прокси или в межсетевом экране между ними.

Почему это происходит

Как исправить

  1. 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. 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. 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/")

Связанные ошибки

Открыть всю базу ошибок подписей