错误信息
code: 'ERR_SSL_WRONG_VERSION_NUMBER'
也可能输出为
- ERR_SSL_WRONG_VERSION_NUMBER
完整消息中嵌入了线程 ID 和源文件路径,例如“60747095FFFF0000:error:0A00010B:SSL routines:tls_validate_record_header:wrong version number:../deps/openssl/openssl/ssl/record/methods/tlsany_meth.c:77:”,因此应按错误代码搜索。tls.connect() 和 fetch() 设置的代码是 ERR_SSL_WRONG_VERSION_NUMBER;https.request() 则以“write EPROTO …”报告同样的原因,代码为 EPROTO。
Node.js tls.connect / fetch (undici) — OpenSSL SSL_R_WRONG_VERSION_NUMBER; https.request reports it as write EPROTO
含义
Node.js 发起了 TLS 握手,但收到的回复不是 TLS 记录,因此 OpenSSL 在校验记录头时失败了。对端在这个端口上使用的是明文:HTTP 服务器、只接受纯 HTTP 的代理,或者尚未执行 STARTTLS 的 SMTP 服务器。尽管错误名称如此,证书和 TLS 版本都没有问题。
原因
用 https:// 访问提供纯 HTTP 服务的端口
常见本地开发服务器、位于终止 TLS 的代理后面的内部服务,或者环境变量中写错的端口号。
HTTPS_PROXY 或 npm 的 https-proxy 写成了 https://
常见大多数正向代理从客户端接收纯 HTTP,再建立 CONNECT 隧道;代理 URL 写成 https:// 会让客户端直接与代理本身开始 TLS 握手。
对 STARTTLS 端口使用隐式 TLS
偶见在 587 或 25 端口上配置了 secure: true 的邮件库会立即尝试 TLS,而服务器要求先用明文完成 SMTP 问候。
修复方法
- 1.
查明端口使用的协议
用 http:// 访问该端口;如果有响应,就改用 http:// 或真正的 TLS 端口。
bash curl -si http://127.0.0.1:8080/ | head -1 # HTTP answers: use http:// or the TLS port openssl s_client -connect 127.0.0.1:8443 -brief </dev/null - 2.
代理 URL 使用 http://
代理 URL 中的协议描述的是与代理之间的连接,而不是与目标之间的连接;HTTPS 目标仍然会通过隧道获得端到端的 TLS。
bash # Proxy URLs for HTTPS traffic normally start with http:// (CONNECT tunnel) export HTTPS_PROXY=http://proxy.example.net:3128 npm config set https-proxy http://proxy.example.net:3128 - 3.
邮件:587 端口用 STARTTLS,465 端口用隐式 TLS
在 nodemailer 中,secure: true 用于 465 端口;在 587 端口上保持 secure: false,并要求使用 STARTTLS。
js // SMTP: secure: true only for implicit TLS (465); 587 upgrades with STARTTLS import nodemailer from "nodemailer"; const transport = nodemailer.createTransport({ host: "smtp.example.com", port: 587, secure: false, requireTLS: true });
相关错误
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)[SSL: WRONG_VERSION_NUMBER] wrong version numberPython ssl module (OpenSSL)http: server gave HTTP response to HTTPS clientGo net/http