Mensaje de error
[SSL: WRONG_VERSION_NUMBER] wrong version number
También se muestra como
- ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number
Va seguido de una ubicación en el código fuente como «(_ssl.c:1082)». urllib lo muestra dentro de «<urlopen error …>», y requests y urllib3, dentro de «Max retries exceeded … (Caused by SSLError(…))».
Python ssl module (OpenSSL) — ssl.SSLError, SSL_R_WRONG_VERSION_NUMBER
Qué significa
Python inició un handshake TLS y los bytes que llegaron de vuelta no son un registro TLS: OpenSSL los lee como el encabezado de un registro con una versión de protocolo imposible. En la práctica, el otro extremo habla en texto plano en ese puerto: un servidor HTTP, un proxy que espera HTTP sin cifrar o un servidor SMTP que espera el intercambio de saludo previo a STARTTLS.
Por qué ocurre
https:// a un puerto HTTP sin cifrar
frecuenteLos servidores de desarrollo, los servicios internos detrás de un balanceador de carga que termina TLS y los endpoints de métricas suelen escuchar en HTTP sin cifrar. Usar https:// con su puerto produce este error de inmediato.
El proxy está configurado como https:// pero habla HTTP
frecuenteHTTPS_PROXY=https://proxy:3128 o proxies={"https": "https://…"} hacen que urllib3 inicie TLS con el proxy. Desde urllib3 1.26 eso se respeta literalmente, y la mayoría de los proxies corporativos solo aceptan HTTP sin cifrar de los clientes.
smtplib.SMTP_SSL en un puerto STARTTLS
frecuenteEl puerto 587 (y el 25) empieza en texto plano y pasa a TLS con STARTTLS; el TLS implícito está en el 465. SMTP_SSL contra el 587 falla de esta manera, igual que IMAP4_SSL contra el 143.
Un portal cautivo o un filtro responde en HTTP sin cifrar
ocasionalLas redes Wi-Fi de hoteles o para invitados y algunos equipos de seguridad interceptan la conexión y responden con una página HTTP.
Cómo solucionarlo
- 1.
Averiguar qué protocolo habla el puerto
Haz una solicitud al puerto con http:// y prueba un handshake TLS con openssl s_client; después usa el esquema correspondiente o el puerto correcto.
bash curl -si http://127.0.0.1:8080/ | head -1 # an HTTP status line: the port is plain HTTP openssl s_client -connect 127.0.0.1:8443 -brief </dev/null # a TLS summary: the port speaks TLS - 2.
Escribir las URL de proxy con http://
La entrada https del diccionario proxies indica el proxy para los destinos HTTPS; el esquema de su URL describe cómo comunicarse con el propio proxy. El tráfico hacia el destino sigue siendo TLS de extremo a extremo.
python import requests # Most forward proxies take plain HTTP from the client and tunnel TLS with CONNECT proxies = {"https": "http://proxy.example.net:3128"} # http:// here, not https:// requests.get("https://api.example.com/", proxies=proxies) - 3.
Correo: usar la clase que corresponde al puerto
Usa SMTP + starttls() en el 587 y SMTP_SSL en el 465; la misma regla se aplica a imaplib y poplib.
python import smtplib, ssl ctx = ssl.create_default_context() # Port 587: plain connection first, then STARTTLS with smtplib.SMTP("mail.example.com", 587) as s: s.starttls(context=ctx) # Port 465: implicit TLS from the first byte with smtplib.SMTP_SSL("mail.example.com", 465, context=ctx) as s: s.noop()
Errores relacionados
curl: (35) TLS connect error: error:0A00010B:SSL routines::wrong version numbercurl (OpenSSL backend)SSL routines:tls_validate_record_header:wrong version numberOpenSSL 3 (openssl s_client and any OpenSSL-based client)code: 'ERR_SSL_WRONG_VERSION_NUMBER'Node.js tls.connect / fetch (undici)[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocolPython ssl module (OpenSSL)