Mensaje de error
curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
También se muestra como
- curl: (56) OpenSSL SSL_read: OpenSSL/3.5.7: error:0A000126:SSL routines::unexpected eof while reading, errno 0
Las versiones recientes de curl insertan la versión de la biblioteca TLS después de «SSL_read: » (por ejemplo, «OpenSSL/3.5.7: »). OpenSSL 1.1.1 no informaba de esta situación así; en 1.1.1 el mismo truncamiento suele aparecer como «curl: (18) transfer closed with N bytes remaining to read».
curl (OpenSSL 3 backend) — CURLE_RECV_ERROR, SSL_R_UNEXPECTED_EOF_WHILE_READING
Qué significa
La conexión TLS se estableció y los datos fluían; después, el otro extremo cerró la conexión TCP sin enviar antes el close_notify de TLS, mientras curl todavía esperaba más datos. OpenSSL 3 informa de ese final abrupto como un error en lugar de como un final normal del flujo, porque la ausencia de close_notify es justo el aspecto que tiene un ataque de truncamiento. curl lo notifica como un fallo de recepción (código de salida 56).
Por qué ocurre
El proceso del servidor se cayó o agotó el tiempo de espera a mitad de la respuesta
frecuenteUn worker de la aplicación terminado por un tiempo de espera o por falta de memoria, el reinicio de un worker de PHP-FPM o Gunicorn, o un upstream que se rinde cierran el socket mientras todavía se está enviando el cuerpo de la respuesta.
Un dispositivo intermedio cortó la conexión
frecuenteLos firewalls, las pasarelas NAT, los proxies corporativos y los balanceadores de carga que imponen límites de inactividad o de duración máxima pueden cortar a nivel TCP una descarga larga o una respuesta lenta, sin ningún cierre TLS por parte del servidor.
El servidor termina las respuestas sin close_notify
ocasionalAlgunos servidores web integrados, versiones antiguas de IIS y servidores TLS escritos a mano cierran el socket sin un cierre TLS. Con respuestas HTTP delimitadas por el cierre de la conexión, los clientes con OpenSSL 3 informan de cada una de esas respuestas como este error.
Un límite de tamaño del cuerpo interrumpió la transferencia
ocasionalLos límites de subida (client_max_body_size, reglas del WAF) o las cuotas de descarga a veces restablecen la conexión en lugar de devolver una respuesta 413 o 403 adecuada.
Cómo solucionarlo
- 1.
Averiguar qué salto cierra la conexión
Anota cuántos bytes y cuántos segundos pasan antes del error y luego repite la solicitud directamente contra el backend. Un corte en un número redondo de segundos apunta a un tiempo de espera de un proxy o un balanceador de carga.
bash # How much arrived, and for how long, before the connection died? curl -sv --trace-time https://api.example.com/export.csv -o out.csv 2>&1 | tail -20 # Same request directly to the backend, bypassing the proxy / load balancer curl -sv --resolve api.example.com:443:10.0.0.12 https://api.example.com/export.csv -o out.csv - 2.
Aumentar el tiempo de espera que se agota
Sube el límite del componente que corta la conexión por encima del tiempo de respuesta legítimo más largo, o haz que el endpoint lento responda más rápido (usa streaming o paginación en las exportaciones grandes).
text # nginx in front of a slow upstream (both default to 60s) proxy_read_timeout 300s; proxy_send_timeout 300s; # Load balancers: set the idle timeout above the longest legitimate response time - 3.
Reintentar las transferencias idempotentes
En descargas por enlaces poco fiables, deja que curl reintente y reanude. Esto trata el síntoma en el cliente mientras se investiga el lado del servidor.
bash # For idempotent downloads: retry, and resume where the transfer stopped curl --retry 5 --retry-all-errors -C - -o big.iso https://downloads.example.com/big.iso - 4.
Código del servidor: cerrar bien las conexiones TLS
Envía close_notify antes de cerrar el socket (SSL_shutdown en OpenSSL, unwrap() en Python, Close() en un tls.Conn de Go) y delimita los cuerpos HTTP con Content-Length o con codificación chunked, para que un final limpio no sea ambiguo.
python # Server code: shut TLS down cleanly so the peer receives close_notify conn.unwrap() # Python ssl.SSLSocket: sends close_notify before closing conn.close()
Errores relacionados
error:0A000126:SSL routines::unexpected eof while readingOpenSSL 3[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocolPython ssl module (OpenSSL)GnuTLS recv error (-110): The TLS connection was non-properly terminated.git over HTTPS with libcurl-gnutls (Debian, Ubuntu)curl: (35) TLS connect error: error:0A00010B:SSL routines::wrong version numbercurl (OpenSSL backend)