跳到主要内容
ecdsa.com
Node.js tls.connect / fetch (undici)Node.js crypto 模块

错误信息

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 版本都没有问题。

原因

修复方法

  1. 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. 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. 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 });

相关错误

浏览完整的签名错误库