Saltar al contenido
ecdsa.com
Python ssl module (OpenSSL)cryptography de Python

Mensaje de error

[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol

También se muestra como

  • ssl.SSLEOFError: EOF occurred in violation of protocol

Con OpenSSL 3, Python muestra el código de motivo «[SSL: UNEXPECTED_EOF_WHILE_READING]»; con OpenSSL 1.1.1, el texto es solo «EOF occurred in violation of protocol». Le sigue una ubicación en el código fuente como «(_ssl.c:1082)».

Python ssl module (OpenSSL) — ssl.SSLEOFError, SSL_R_UNEXPECTED_EOF_WHILE_READING

Qué significa

El otro extremo cerró la conexión TCP mientras Python seguía en el handshake TLS (o a mitad de la lectura de datos), sin enviar una alerta TLS ni close_notify. OpenSSL trata ese cierre silencioso como una violación del protocolo. Python no puede saber por qué se fue el otro extremo; el motivo está en el servidor, en un proxy o en un firewall intermedio.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Reproducir el handshake con openssl s_client

    Si s_client también se desconecta, cambia el SNI y la versión de TLS para ver qué rechaza el servidor; si s_client funciona, compara su configuración con la de tu cliente Python (proxy, SNI, versiones).

    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.

    Comprobar las variables de entorno del proxy

    requests, urllib y pip respetan HTTPS_PROXY y NO_PROXY. Corrige el esquema de la URL del proxy y excluye los hosts internos a los que hay que llegar directamente.

    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.

    Reintentar cuando la causa es transitoria

    Ante la limitación de frecuencia y las redes inestables, los reintentos con espera progresiva (backoff) convierten los cortes esporádicos en éxitos más lentos; no arreglan un servidor que siempre rechaza el handshake.

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

Errores relacionados

Explorar toda la base de datos de errores de firma