Mensaje de error
[SSL: DH_KEY_TOO_SMALL] dh key too small
Va seguido de una ubicación en el código fuente como «(_ssl.c:1082)». curl y otros clientes de OpenSSL imprimen el mismo motivo como «dh key too small».
Python ssl module (OpenSSL, security level 2) — ssl.SSLError, SSL_R_DH_KEY_TOO_SMALL
Qué significa
El servidor eligió un intercambio de claves Diffie-Hellman de campo finito (DHE) con un grupo más pequeño de lo que acepta el cliente, normalmente de 1024 bits. Python 3.10 y posteriores usan el nivel de seguridad 2 de OpenSSL, que exige DH de al menos 2048 bits, así que el cliente aborta el handshake. El problema no es el certificado del servidor.
Por qué ocurre
El servidor usa un grupo DH de 1024 bits
frecuenteVersiones antiguas de Apache httpd (antes de la 2.4.7 usaban parámetros fijos de 1024 bits), servidores antiguos basados en Java y configuraciones que todavía cargan un archivo dhparam generado hace años. La investigación Logjam (2015) demostró que DH de 1024 bits está al alcance de atacantes con muchos recursos.
El nivel de seguridad predeterminado más estricto de Python
frecuentePython 3.10 subió su valor predeterminado al nivel de seguridad 2 de OpenSSL. Un código que se conectaba sin problemas con Python 3.9 puede fallar tras actualizar, aunque el servidor no haya cambiado.
Dispositivos integrados y equipos dedicados
ocasionalLas interfaces de administración de impresoras, centrales telefónicas (PBX) y equipos industriales a menudo solo ofrecen DHE con grupos pequeños.
Cómo solucionarlo
- 1.
Confirmar el tamaño del intercambio de claves
Conéctate una vez con openssl s_client en el nivel de seguridad 1 y lee «Server Temp Key».
bash # "Server Temp Key: DH, 1024 bits" confirms the weak group openssl s_client -connect legacy.example.com:443 -servername legacy.example.com \ -cipher 'DEFAULT:@SECLEVEL=1' </dev/null 2>/dev/null | grep 'Server Temp Key' - 2.
Propietarios del servidor: usar ECDHE o un grupo de 2048 bits
Da preferencia a los conjuntos ECDHE (y a TLS 1.3); si se necesita DHE, configura un grupo del RFC 7919 de al menos 2048 bits.
text # nginx: prefer ECDHE; if DHE must stay, use a 2048-bit (or larger) group ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_dhparam /etc/nginx/ffdhe2048.pem; # RFC 7919 group - 3.
Solución provisional: bajar el nivel de seguridad para un solo host
La cadena «DEFAULT:@SECLEVEL=1» en un contexto dedicado acepta DH de 1024 bits solo para ese host. No la uses en contextos compartidos ni predeterminados: también acepta otros parámetros débiles.
python # Temporary workaround for one legacy host: security level 1 accepts 1024-bit DH import ssl, urllib.request ctx = ssl.create_default_context() ctx.set_ciphers("DEFAULT:@SECLEVEL=1") urllib.request.urlopen("https://legacy.example.com/", context=ctx)
Errores relacionados
[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failurePython ssl module (OpenSSL)[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabledPython ssl module (OpenSSL 3)curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handsh…curl (OpenSSL backend)